diff --git a/src/main/debugger/org/bdware/sc/debugger/DebugMain.java b/src/main/debugger/org/bdware/sc/debugger/DebugMain.java index 8ce15f1..4a22409 100644 --- a/src/main/debugger/org/bdware/sc/debugger/DebugMain.java +++ b/src/main/debugger/org/bdware/sc/debugger/DebugMain.java @@ -63,7 +63,9 @@ public class DebugMain { = new ResultCallback() { @Override public void onResult(String str) { - + if(str.contains("Error")) { + LOGGER.error("Some error happens: " + str); + } LOGGER.info("[PrintCB] " + str); } }; diff --git a/src/main/java/org/bdware/sc/ContractProcess.java b/src/main/java/org/bdware/sc/ContractProcess.java index 51be291..323b3d3 100644 --- a/src/main/java/org/bdware/sc/ContractProcess.java +++ b/src/main/java/org/bdware/sc/ContractProcess.java @@ -16,6 +16,7 @@ import org.bdware.analysis.gas.PPCount; import org.bdware.analysis.taint.TaintBB; import org.bdware.analysis.taint.TaintCFG; import org.bdware.analysis.taint.TaintResult; +import org.bdware.doip.audit.EndpointConfig; import org.bdware.sc.ContractResult.Status; import org.bdware.sc.bean.*; import org.bdware.sc.boundry.JavaScriptEntry; @@ -49,6 +50,7 @@ import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*; +import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class ContractProcess { @@ -522,10 +524,7 @@ public class ContractProcess { // doipModule的话,拉起DoipServer服务端口 if(cn.getYjsType() == YjsType.DoipModule) { // 只有一台机器去更新Router中的repoInfo就可以了 - if(JavaScriptEntry.shardingID == 0) { - DoipClusterServer server = DoipClusterServer.getDOOPServerInstance(); - server.updateRepoInfo(contract, cn); - } + updateRepoInfo(contract.getCreateParam()); invokeOnStartingDoipServer(cn, contract.getCreateParam()); } @@ -570,10 +569,6 @@ public class ContractProcess { fun.appendBeforeInvokeHandler(argSchemaHandler); } - if (fun.isDoipOperation()) { - fun.appendBeforeInvokeHandler(DOOPHandler.createDOOPHandler()); - } - if (fun.isExport()) { //if(fun.annotations...) AccessHandler accessHandler = createHandlerIfExist(fun,fun.annotations,AccessHandler.class); @@ -600,6 +595,10 @@ public class ContractProcess { fun.appendAfterInvokeHandler(new HomomorphicDecryptHandler(fun)); } + if (fun.isDoipOperation()) { + fun.appendBeforeInvokeHandler(DOOPBeforeExecHandler.createDOOPHandler()); + fun.appendAfterInvokeHandler(DOOPAfterExecHandler.createDOOPHandler()); + } } } @@ -665,11 +664,7 @@ public class ContractProcess { // doipModule的话,拉起DoipServer服务端口 if(cn.getYjsType() == YjsType.DoipModule) { - // 只有一台机器去更新Router中的repoInfo就可以了 - if(JavaScriptEntry.shardingID == 0) { - DoipClusterServer server = DoipClusterServer.getDOOPServerInstance(); - server.updateRepoInfo(contract, cn); - } + updateRepoInfo(contract.getCreateParam()); invokeOnStartingDoipServer(cn, contract.getCreateParam()); } @@ -682,9 +677,35 @@ public class ContractProcess { } } + public void updateRepoInfo(JsonElement arg) throws Exception { + // 只有0号节点需要初始化IRP连接去updateRepoInfo + if(JavaScriptEntry.shardingID == 0) { + // DOOP relevant logic + DoipClusterServer server = DoipClusterServer.getDOOPServerInstance(); + if(server == null) { + JsonObject createParams = arg.getAsJsonObject(); + if(createParams.has("router")) { + JsonElement routerInfo = createParams.get("router"); + if(!routerInfo.isJsonObject()) throw new Exception("Provide wrong router info in create params to DoipModule"); + else { + EndpointConfig endpointConfig = JsonUtil.GSON.fromJson(routerInfo.getAsJsonObject(), EndpointConfig.class); + DoipClusterServer.createDOOPServerInstance(endpointConfig); + } + } else { + throw new Exception("DoipModule should provide router info in create params"); + } + + server = DoipClusterServer.getDOOPServerInstance(); + } + + // 只有一台机器去更新Router中的repoInfo就可以了 + server.updateRepoInfo(contract, cn); + } + } + public void invokeOnStartingDoipServer(ContractNode cn, JsonElement arg) { ContractRequest onStartingDoipServer = new ContractRequest(); - onStartingDoipServer.setAction("invokeOnStartingDoipServer"); + onStartingDoipServer.setAction("onServerStart"); if (arg == null) { if (engine != null && engine.getManifest() != null && engine.getManifest().createParam != null) arg = engine.getManifest().createParam; @@ -699,7 +720,7 @@ public class ContractProcess { } else { onStartingDoipServer.setRequesterDOI("empty"); } - FunctionNode funNode = cn.getFunction("invokeOnStartingDoipServer"); + FunctionNode funNode = cn.getFunction("onServerStart"); try { JsonElement onStartingDoipServerRes = invoke(onStartingDoipServer, funNode).result; @@ -724,7 +745,7 @@ public class ContractProcess { } } catch (Exception e) { - LOGGER.error("DoipLocalSingleton cannot starts properly, plz check the invokeOnStartingDoipServer function"); + LOGGER.error("DoipLocalSingleton cannot starts properly, plz check the onServerStart function"); e.printStackTrace(); } } @@ -738,7 +759,7 @@ public class ContractProcess { } else { funcArgs[2] = "empty"; } - Object result = engine.invokeFunction("invokeOnStartingDoipServer", funcArgs); + Object result = engine.invokeFunction("onServerStart", funcArgs); Map resMap = (Map) result; try { if (!resMap.containsKey("doipAddr")) { @@ -747,7 +768,7 @@ public class ContractProcess { DoipClusterServer.startDoipServer(resMap.get("doipAddr")); } } catch (Exception e) { - LOGGER.error("DoipLocalSingleton cannot starts properly, plz check the invokeOnStartingDoipServer function"); + LOGGER.error("DoipLocalSingleton cannot starts properly, plz check the onServerStart function"); e.printStackTrace(); } } diff --git a/src/main/java/org/bdware/sc/compiler/AnnotationProcessor.java b/src/main/java/org/bdware/sc/compiler/AnnotationProcessor.java index f356f71..816b12a 100644 --- a/src/main/java/org/bdware/sc/compiler/AnnotationProcessor.java +++ b/src/main/java/org/bdware/sc/compiler/AnnotationProcessor.java @@ -10,7 +10,7 @@ public abstract class AnnotationProcessor { } public void processFunction( - AnnotationNode anno, ContractNode contractNode, FunctionNode functionNode) { + AnnotationNode anno, ContractNode contractNode, FunctionNode functionNode) throws Exception { return; } } diff --git a/src/main/java/org/bdware/sc/compiler/YJSCompiler.java b/src/main/java/org/bdware/sc/compiler/YJSCompiler.java index 45b9f93..e69437d 100644 --- a/src/main/java/org/bdware/sc/compiler/YJSCompiler.java +++ b/src/main/java/org/bdware/sc/compiler/YJSCompiler.java @@ -119,18 +119,6 @@ public class YJSCompiler { ContractManifest cm = JsonUtil.GSON.fromJson( new InputStreamReader(manifestInput), ContractManifest.class); - - // DOOP relevant logic - ZipEntry routerConfig = zf.getEntry("/router.json"); - if (null == routerConfig) { - routerConfig = zf.getEntry("router.json"); - } - if(null != routerConfig) { - InputStream routerInput = zf.getInputStream(routerConfig); - EndpointConfig endpointConfig = JsonUtil.GSON.fromJson(new InputStreamReader(routerInput), EndpointConfig.class); - DoipClusterServer.createDOOPServerInstance(endpointConfig); - } - // 如果没有就不限制,根据gas进行插装 if (0L != cm.getInsnLimit()) { LOGGER.info("++++++++++++++++++++++true"); @@ -189,7 +177,7 @@ public class YJSCompiler { return czb; } - public ContractNode compile(InputStream input, String fileName) throws IOException { + public ContractNode compile(InputStream input, String fileName) throws Exception { // 词法分析 JavaScriptLexer lexer = new JavaScriptLexer(new ANTLRInputStream(input)); lexer.setUseStrictDefault(true); @@ -209,7 +197,7 @@ public class YJSCompiler { return contract; } - private void handleAnnotation(ContractNode contractNode) { + private void handleAnnotation(ContractNode contractNode) throws Exception { for (AnnotationNode node : contract.annotations) { AnnotationProcessor processor = findProcessor(node); if (processor != null) { 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..0e254b5 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; @@ -12,7 +13,7 @@ import org.bdware.sc.node.FunctionNode; // DOOP is designed for DoipModule which contains specific functions for RepositoryHandler public class DOOP extends AnnotationProcessor { @Override - public void processFunction(AnnotationNode anno, ContractNode contractNode, FunctionNode functionNode) { + public void processFunction(AnnotationNode anno, ContractNode contractNode, FunctionNode functionNode) throws Exception { // 通过DOOP注解,解析对应的值,并放进对应的FunctionNode中 // 注解必须暴露出来昂!!! functionNode.setIsExport(true); @@ -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/JSONTool.java b/src/main/java/org/bdware/sc/engine/JSONTool.java index abac953..5c193d9 100644 --- a/src/main/java/org/bdware/sc/engine/JSONTool.java +++ b/src/main/java/org/bdware/sc/engine/JSONTool.java @@ -1,6 +1,8 @@ package org.bdware.sc.engine; import com.google.gson.*; +import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.sc.util.JsonUtil; import wrp.jdk.nashorn.api.scripting.ScriptObjectMirror; import wrp.jdk.nashorn.internal.objects.NativeArray; import wrp.jdk.nashorn.internal.runtime.PropertyMap; @@ -147,7 +149,9 @@ public class JSONTool { return jsonObject; } else if (obj.getClass() == jdk.internal.dynalink.beans.StaticClass.class) { return JsonNull.INSTANCE; - } else if (obj instanceof Number) { + } else if (obj.getClass() == DoipMessage.class) { + return JsonUtil.fromJson(JsonUtil.toJson(obj), JsonObject.class); + }else if (obj instanceof Number) { return new JsonPrimitive((Number) obj); } else if (obj instanceof String) { return new JsonPrimitive((String) obj); 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..3bcf474 --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java @@ -0,0 +1,157 @@ +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.*; +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.engine.JSONTool; +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) { + DoipMessagePacker doipMessagePacker = (DoipMessagePacker) originDoipMsgPacker; + originDoipMsg = doipMessagePacker.rawDoipMsg; + + // if http, directly return + if (doipMessagePacker.source.equals("http")) { + return argPacks; + } else { + // pack + JsonObject jsonObjectRes = JSONTool.convertMirrorToJson(argPacks.ret).getAsJsonObject(); + + // validate json response + JsonElement jsonResponseRules = getRulesForJsonResponse(curOp); + ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonObjectRes); + 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; + + // 和HTTP一样,所有需要的字段自己封装,校验规则也比较简单,这里只做简单的包装返回即可!!! + if(header != null) { + originDoipMsg.header = JsonUtil.fromJson(header, MessageHeader.class); + // response字段根据白皮书上的规定,处于header下,人为包装到parameters的response中 + String headerRespCode = header.get("response") != null ? header.get("response").getAsString() : null; + if(headerRespCode != null) { + if (originDoipMsg.header.parameters == null) originDoipMsg.header.parameters = new HeaderParameter(null, null); + originDoipMsg.header.parameters.response = DoipResponseCode.valueOf(headerRespCode); + } + } + + if(body != null) { + originDoipMsg.body.encodedData = body.getBytes(StandardCharsets.UTF_8); + } + + argPacks.ret = originDoipMsg; + return argPacks; + } + } else { + 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 75% 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..0437d1f 100644 --- a/src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java @@ -5,7 +5,6 @@ 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; @@ -20,16 +19,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,30 +97,12 @@ 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(); // taking Extension into consideration JsonObject header = jsonParams.get("header") != null ? jsonParams.get("header").getAsJsonObject() : null; - JsonObject body = jsonParams.get("body") != null ? jsonParams.get("body").getAsJsonObject() : null; + String body = jsonParams.get("body") != null ? jsonParams.get("body").getAsString() : null; DoipMessage doipMessage = null; switch(httpOperation) { case Hello: @@ -133,7 +114,7 @@ public class DOOPHandler implements AnnotationHook { case Update: doipMessage = new DoipMessageFactory.DoipMessageBuilder() .createRequest(header.get("identifier").getAsString(), httpOperation.getName()) - .setBody(body.getAsString().getBytes(StandardCharsets.UTF_8)) + .setBody(body.getBytes(StandardCharsets.UTF_8)) .create(); break; case Search: @@ -172,7 +153,7 @@ public class DOOPHandler implements AnnotationHook { } if(body != null) { - extensionBuilder.setBody(body.getAsString().getBytes(StandardCharsets.UTF_8)); + extensionBuilder.setBody(body.getBytes(StandardCharsets.UTF_8)); } doipMessage = extensionBuilder.create(); @@ -185,36 +166,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..0ed220f 100644 --- a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java +++ b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java @@ -1,18 +1,19 @@ package org.bdware.sc.handler; import com.google.gson.Gson; -import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import io.netty.channel.ChannelHandlerContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.doip.codec.doipMessage.HeaderParameter; import org.bdware.doip.codec.operations.BasicOperations; import org.bdware.doip.endpoint.server.DoipRequestHandler; 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.boundry.JavaScriptEntry; import org.bdware.sc.entity.DoipMessagePacker; import org.bdware.sc.node.FunctionNode; @@ -39,8 +40,12 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler return instance; } - public void addDoipOperation(FunctionNode function) { - doipFunctionNodeMap.put(function.getDoipOperationInfo().operationName, function); + public void addDoipOperation(FunctionNode function) throws Exception { + String operationName = function.getDoipOperationInfo().operationName; + if (doipFunctionNodeMap.containsKey(operationName)) { + throw new Exception("Contract is wrong: One DO operation maps multiple functions"); + } + doipFunctionNodeMap.put(operationName, function); } @Override @@ -139,7 +144,16 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler try { // 改变调用的函数 + 构造DoipMessagePacker Object ret = ContractProcess.instance.engine.executeWithoutLock(fn, contractRequest, arg); - return DOOPHandler.convertJsonResponseToDoipMessage(fn, (JsonElement) ret, msg); + DoipMessage finalDoipMsg = (DoipMessage) ret; + finalDoipMsg.requestID = msg.requestID; + if(finalDoipMsg.header.parameters == null) { + finalDoipMsg.header.parameters = new HeaderParameter("", ""); + } + if(finalDoipMsg.header.parameters.attributes == null) { + finalDoipMsg.header.parameters.attributes = new JsonObject(); + } + finalDoipMsg.header.parameters.attributes.addProperty("nodeID", String.valueOf(JavaScriptEntry.shardingID)); + return finalDoipMsg; } 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 e202388..e375c57 100644 --- a/src/main/java/org/bdware/sc/server/DoipClusterServer.java +++ b/src/main/java/org/bdware/sc/server/DoipClusterServer.java @@ -15,6 +15,7 @@ import org.bdware.irp.exception.IrpClientException; import org.bdware.irp.stateinfo.StateInfoBase; import org.bdware.sc.ContractProcess; import org.bdware.sc.bean.Contract; +import org.bdware.sc.bean.JoinInfo; import org.bdware.sc.bean.RouteInfo; import org.bdware.sc.handler.DOOPRequestHandler; import org.bdware.sc.node.ContractNode; @@ -96,15 +97,19 @@ public class DoipClusterServer extends DoipServerImpl { // doipOperationName和对应的routeFunctionName的对应关系,存储方式为doipOperationName: routeFunctionName JsonObject methodRouteInfoMap = new JsonObject(); + // doipOperationName和对应的routeFunctionName的对应关系,存储方式为doipOperationName: routeFunctionName + JsonObject methodJoinInfoMap = new JsonObject(); + // 所有Router中用得到的函数(例如Route函数和Route函数依赖的相关函数) JsonObject functions = new JsonObject(); // 维护RouteInfo,将RouteInfo和doipOperationName的映射关系,以及所有Router中用得到的函数都维护好 - maintainRouteInfo(cn, methodRouteInfoMap, functions); + maintainRouteJoinInfo(cn, methodRouteInfoMap, methodJoinInfoMap, functions); if(clusterInfo != null) repoHandleValues.add("clusterInfo", clusterInfo); if(!functions.equals(new JsonObject())) repoHandleValues.add("functions", functions); if(!methodRouteInfoMap.equals(new JsonObject())) repoHandleValues.add("routeInfo", methodRouteInfoMap); + if(!methodJoinInfoMap.equals(new JsonObject())) repoHandleValues.add("joinInfo", methodJoinInfoMap); repoInfo.handleValues.addProperty("cluster", repoHandleValues.toString()); String updateRepoInfoRes = repoIrpClient.reRegister(repoInfo); @@ -117,7 +122,7 @@ public class DoipClusterServer extends DoipServerImpl { } } - public void maintainRouteInfo(ContractNode cn, JsonObject methodRouteInfoMap, JsonObject functions) { + public void maintainRouteJoinInfo(ContractNode cn, JsonObject methodRouteInfoMap, JsonObject methodJoinInfoMap, JsonObject functions) { // all functions存了ContractNode中,所有的FunctionNode List allFunctions = cn.getFunctions(); // gson是Gson工具类昂!!! @@ -128,25 +133,47 @@ public class DoipClusterServer extends DoipServerImpl { String doipOperationName = doipFunctionNodes.getKey(); FunctionNode doipFunctionNode = doipFunctionNodes.getValue(); RouteInfo doipFunctionRouteInfo = doipFunctionNode.getRouteInfo(); + JoinInfo doipFunctionJoinInfo = doipFunctionNode.getJoinInfo(); - // 对于routerInfo进行处理,对于routeInfo进行维护 + // 对于RouterInfo进行维护 if(doipFunctionRouteInfo != null) { + // 建立method和RouteInfo的映射 methodRouteInfoMap.addProperty(doipOperationName, gson.toJson(doipFunctionRouteInfo)); if(doipFunctionRouteInfo.funcName != null) { String routeFunctionName = doipFunctionRouteInfo.funcName; - for(FunctionNode functionNode : allFunctions) { - // find Route Function - if(functionNode.functionName.equals(routeFunctionName)) { - functions.addProperty(functionNode.functionName, functionNode.plainText()); + packSourceFunctionAndDependentFunctions(allFunctions, routeFunctionName, functions); + } + } - // add all dependentFunction to the "functions" struct - for (String dependentFunctionName : functionNode.getDependentFunctions()) { - for (FunctionNode f : cn.getFunctions()) { - if(f.functionName.equals(dependentFunctionName) && !functions.has(dependentFunctionName)) { - functions.addProperty(dependentFunctionName, f.plainText()); - } - } - } + // 对于JoinInfo进行维护 + if(doipFunctionJoinInfo != null) { + // 建立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); + } + } + } + } + + public void packSourceFunctionAndDependentFunctions(List allFunctions, String sourceFunctionName, JsonObject functions) { + for(FunctionNode functionNode : allFunctions) { + // add sourceFunction + if(functionNode.functionName.equals(sourceFunctionName)) { + functions.addProperty(functionNode.functionName, functionNode.plainText()); + + // find all dependent functions to the "functions" struct + for (String dependentFunctionName : functionNode.getDependentFunctions()) { + for (FunctionNode f : allFunctions) { + if(f.functionName.equals(dependentFunctionName) && !functions.has(dependentFunctionName)) { + functions.addProperty(dependentFunctionName, f.plainText()); } } } diff --git a/src/test/java/org/bdware/sc/parser/YJSParserTest.java b/src/test/java/org/bdware/sc/parser/YJSParserTest.java index 1f7ac9c..9e62db9 100644 --- a/src/test/java/org/bdware/sc/parser/YJSParserTest.java +++ b/src/test/java/org/bdware/sc/parser/YJSParserTest.java @@ -67,7 +67,7 @@ public class YJSParserTest { ContractNode cn = compiler.compile(resource, "rrr.yjs"); new DesktopEngine(); System.out.println(new Gson().toJson(cn)); - } catch (IOException e) { + } catch (Exception e) { e.printStackTrace(); } }