diff --git a/src/main/java/org/bdware/sc/ContractProcess.java b/src/main/java/org/bdware/sc/ContractProcess.java index ac3eea1..a9875d4 100644 --- a/src/main/java/org/bdware/sc/ContractProcess.java +++ b/src/main/java/org/bdware/sc/ContractProcess.java @@ -32,6 +32,7 @@ import org.bdware.sc.engine.hook.*; import org.bdware.sc.handler.ContractHandler; import org.bdware.sc.index.TimeSerialIndex; import org.bdware.sc.node.*; +import org.bdware.sc.server.DoipServerTest; import org.bdware.sc.trace.ProgramPointCounter; import org.bdware.sc.util.FileUtil; import org.bdware.sc.util.HashUtil; @@ -559,6 +560,10 @@ public class ContractProcess { fun.appendBeforeInvokeHandler(argSchemaHandler); } + if (fun.isDoipOperation()) { + fun.appendBeforeInvokeHandler(new DOOPHandler()); + } + if (fun.isExport()) { //if(fun.annotations...) fun.appendAfterInvokeHandler(new ObjToJsonHandler()); @@ -643,6 +648,12 @@ public class ContractProcess { jo.add("loadContract", JsonUtil.parseObject(ret)); jo.addProperty("status", ret.status.merge(onCreate.status).toString()); LOGGER.debug("result: " + jo.toString()); + + // doipModule的话,拉起DoipServer服务端口 + if(cn.getYjsType() == YjsType.DoipModule) { + DoipServerTest.main(new String[]{"8080"}); + } + return jo.toString(); } catch (Exception e) { ByteArrayOutputStream bo = new ByteArrayOutputStream(); 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 6529401..a24446d 100644 --- a/src/main/java/org/bdware/sc/compiler/ap/DOOP.java +++ b/src/main/java/org/bdware/sc/compiler/ap/DOOP.java @@ -18,6 +18,7 @@ public class DOOP extends AnnotationProcessor { // 通过DOOP注解,解析对应的值,并放进对应的FunctionNode中 // 注解必须暴露出来昂!!! functionNode.setIsExport(true); + functionNode.setIsDoipOperation(true); functionNode.setDoipOperationInfo(DoipOperationInfo.create(anno, contractNode)); // 维护DOOPRequestHandler @@ -27,6 +28,6 @@ public class DOOP extends AnnotationProcessor { DOOPRequestHandler.instance.addDoipOperation(functionNode); // 维护ContractNode,functionName is useless, use BasicOperation to map the corresponding functionNode - contractNode.updateFunctionMap(functionNode.functionName, functionNode.getDoipOperationInfo().operationType.toString()); + contractNode.updateFunctionMap(functionNode.functionName, functionNode.getDoipOperationInfo().operationName); } } diff --git a/src/main/java/org/bdware/sc/engine/DesktopEngine.java b/src/main/java/org/bdware/sc/engine/DesktopEngine.java index 080b50a..7d7fe5d 100644 --- a/src/main/java/org/bdware/sc/engine/DesktopEngine.java +++ b/src/main/java/org/bdware/sc/engine/DesktopEngine.java @@ -518,10 +518,10 @@ public class DesktopEngine extends JSEngine { input.getRequester().startsWith("event"))) { Object ret; if (fun.isView()) { - ret = executeWithoutLock(fun, input); + ret = executeWithoutLock(fun, input, null); } else { synchronized (this) { - ret = executeWithoutLock(fun, input); + ret = executeWithoutLock(fun, input, null); } } @@ -606,21 +606,25 @@ public class DesktopEngine extends JSEngine { } - private Object executeWithoutLock(FunctionNode fun, ContractRequest input) throws ScriptException, NoSuchMethodException { - Object ret = null; + public Object executeWithoutLock(FunctionNode fun, ContractRequest input, Object injectedArg) throws ScriptException, NoSuchMethodException { // long start = System.currentTimeMillis(); - - for (AnnotationHook handler : fun.beforeExecutionAnnotations()) { - ret = handler.handle(this, new ArgPacks(input, input.getArg(), ret)); + ArgPacks argPack = new ArgPacks(input, input.getArg(), null); + if(injectedArg != null) { + argPack.arg = injectedArg; } + for (AnnotationHook handler : fun.beforeExecutionAnnotations()) { + argPack = handler.handle(this, argPack); + } + // actually invoke! - if (ret == null) { - ret = + // todo 这里invoke应该如何调用,改了一行代码正确吗?input.getArg() -> argPack.arg + if (argPack.ret == null) { + argPack.ret = engine.invokeFunction( input.getAction(), (fun.isHandler() ? JsonUtil.fromJson(input.getArg(), Event.class) - : JSONTool.convertJsonElementToMirror(input.getArg())), + : JSONTool.convertJsonElementToMirror(argPack.arg)), input.getRequester(), input.getRequesterDOI()); } @@ -628,9 +632,9 @@ public class DesktopEngine extends JSEngine { //Mask在after裏面 //System.out.println("afterHook"+contract.Mask); - ret = handler.handle(this, new ArgPacks(input, input.getArg(), ret)); + argPack = handler.handle(this, argPack); } - return ret; + return argPack.ret; } private String extractException(String msg, List stack) { diff --git a/src/main/java/org/bdware/sc/engine/JSONTool.java b/src/main/java/org/bdware/sc/engine/JSONTool.java index cccf9f9..5577b7d 100644 --- a/src/main/java/org/bdware/sc/engine/JSONTool.java +++ b/src/main/java/org/bdware/sc/engine/JSONTool.java @@ -40,6 +40,14 @@ public class JSONTool { return null; } + public static Object convertJsonElementToMirror(Object input) { + if(input instanceof JsonElement) { + return convertJsonElementToMirror((JsonElement) input); + } else { + return input; + } + } + private static JsonElement convertMirrorToJsonInternal(Object obj, Set recorded) { if (recorded.contains(obj)) return JsonNull.INSTANCE; if (obj == null) return JsonNull.INSTANCE; diff --git a/src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java b/src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java new file mode 100644 index 0000000..3d0addb --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java @@ -0,0 +1,101 @@ +package org.bdware.sc.engine.hook; + +import com.google.gson.JsonElement; +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.entity.DoipMessagePacker; +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 java.nio.charset.StandardCharsets; + +public class DOOPHandler implements AnnotationHook { + public DOOPHandler() { + + } + + public static DOOPHandler fromAnnotationNode(FunctionNode funNode, AnnotationNode annoNode) { + return new DOOPHandler(); + } + + @Override + public ArgPacks handle(JSEngine desktopEngine, ArgPacks argPacks) { + Object arg = argPacks.arg; + DoipMessagePacker doipMsgPackerArg = new DoipMessagePacker(); + + if (arg instanceof DoipMessagePacker){ + doipMsgPackerArg = (DoipMessagePacker)arg; + } else { + // validate http request's params + ContractRequest httpReq = argPacks.request; + validateHTTPRequestArgs(httpReq); + + // set doipMsgPackerArg struct's params + doipMsgPackerArg.setSource("http"); + doipMsgPackerArg.rawDoipMsg = convertContractRequestToDoipMessage(httpReq); + } + + argPacks.arg = doipMsgPackerArg; + return argPacks; + } + + public static void validateHTTPRequestArgs(ContractRequest httpReq) { + JsonElement httpArgs = httpReq.getArg(); + BasicOperations curOp = BasicOperations.getDoOp(httpReq.getAction()); + + // get args rules and validate http args + JsonElement httpArgsRules = getRulesForBasicOperation(curOp); + ArgSchemaVisitor visitor = new ArgSchemaVisitor(httpArgs); + visitor.visit(httpArgsRules); + } + + public static JsonElement getRulesForBasicOperation(BasicOperations basicOperation) { + + switch(basicOperation) { + case Hello: + return JsonParser.parseString("{\"!doid\":\"string\"}"); + case Retrieve: + return JsonParser.parseString("{\"!doid\":\"string\", \"!element\":\"boolean\"}"); + default: + return null; + } + } + + public static DoipMessage convertContractRequestToDoipMessage(ContractRequest httpReq) { + BasicOperations httpOperation = BasicOperations.getDoOp(httpReq.getAction()); + DoipMessage doipMessage = new DoipMessageFactory.DoipMessageBuilder().createRequest("", httpReq.getAction()).create(); + switch(httpOperation) { + case Hello: + doipMessage = new DoipMessageFactory.DoipMessageBuilder().createRequest(httpReq.getArg().getAsJsonObject().get("doid").getAsString(), httpReq.getAction()).create(); + break; + case Retrieve: + DoipMessageFactory.DoipMessageBuilder msgBuilder = new DoipMessageFactory.DoipMessageBuilder().createRequest(httpReq.getArg().getAsJsonObject().get("doid").getAsString(), httpReq.getAction()); + msgBuilder = msgBuilder.addAttributes("element", httpReq.getArg().getAsJsonObject().get("element").getAsString()); + doipMessage = msgBuilder.create(); + break; + } + + return doipMessage; + } + + public static DoipMessage convertJsonElementToDoipMessage(JsonElement jsonElementRet, DoipMessage msg) { + DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder(); + + String responseCodeStr = jsonElementRet.getAsJsonObject().get("doipResponseCode").getAsString(); + DoipResponseCode responseCode = DoipResponseCode.UnKnownError; + for (DoipResponseCode resp : DoipResponseCode.values()) { + if (resp.toString().equals(responseCodeStr)) responseCode = resp; + } + + DoipMessage doipRet = builder.createResponse(responseCode, msg).create();; + doipRet.body.encodedData = jsonElementRet.getAsJsonObject().get("body").getAsJsonObject().get("encodedData").getAsString().getBytes(StandardCharsets.UTF_8); + return doipRet; + } +} diff --git a/src/main/java/org/bdware/sc/entity/DoipMessagePacker.java b/src/main/java/org/bdware/sc/entity/DoipMessagePacker.java new file mode 100644 index 0000000..691f970 --- /dev/null +++ b/src/main/java/org/bdware/sc/entity/DoipMessagePacker.java @@ -0,0 +1,25 @@ +package org.bdware.sc.entity; + +import org.bdware.doip.codec.doipMessage.DoipMessage; + +public class DoipMessagePacker { + // the DoipMessagePacker is raised by http/doip + public String source; + // the well-composed DoipMessage + public DoipMessage rawDoipMsg; + + public DoipMessagePacker() {} + + public DoipMessagePacker(String source, DoipMessage rawMsg) { + this.source = source; + this.rawDoipMsg = rawMsg; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } +} diff --git a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java index a40af26..72f0f97 100644 --- a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java +++ b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java @@ -11,11 +11,11 @@ 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.ContractResult; import org.bdware.sc.bean.ContractRequest; +import org.bdware.sc.engine.hook.DOOPHandler; +import org.bdware.sc.entity.DoipMessagePacker; import org.bdware.sc.node.FunctionNode; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @@ -35,7 +35,7 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler } public void addDoipOperation(FunctionNode function) { - doipOperationsMap.put(function.getDoipOperationInfo().operationType.getName(), function); + doipOperationsMap.put(function.getDoipOperationInfo().operationName, function); } @Override @@ -47,13 +47,7 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler fn = doipOperationsMap.get(str); if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); if (fn != null) { - try { - ContractRequest contractRequest = constructContractRequest(fn, msg); - ContractResult res = ContractProcess.instance.engine.executeContract(contractRequest); - return gson.fromJson(res.toString(), DoipMessage.class); - } catch (Exception e) { - e.printStackTrace(); - } + return buildRequestAndInvokeEngine(fn, msg); } } return null; @@ -62,57 +56,82 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler @Override public DoipMessage handleHello(DoipMessage request) { FunctionNode fn = doipOperationsMap.get(BasicOperations.Hello.getName()); - ContractRequest cr = constructContractRequest(fn, request); - JsonElement res = ContractProcess.instance.engine.executeContract(cr).result; - return gson.fromJson(res.toString(), DoipMessage.class); + if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); + if (fn != null) { + return buildRequestAndInvokeEngine(fn, request); + } + return null; } @Override public DoipMessage handleListOps(DoipMessage request) { FunctionNode fn = doipOperationsMap.get(BasicOperations.ListOps.getName()); - ContractRequest cr = constructContractRequest(fn, request); - JsonElement res = ContractProcess.instance.engine.executeContract(cr).result; - return gson.fromJson(res.toString(), DoipMessage.class); + if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); + if (fn != null) { + return buildRequestAndInvokeEngine(fn, request); + } + return null; } @Override public DoipMessage handleCreate(DoipMessage request) { FunctionNode fn = doipOperationsMap.get(BasicOperations.Create.getName()); - ContractRequest cr = constructContractRequest(fn, request); - JsonElement res = ContractProcess.instance.engine.executeContract(cr).result; - return gson.fromJson(res.toString(), DoipMessage.class); + if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); + if (fn != null) { + return buildRequestAndInvokeEngine(fn, request); + } + return null; } @Override public DoipMessage handleUpdate(DoipMessage request) { FunctionNode fn = doipOperationsMap.get(BasicOperations.Update.getName()); - ContractRequest cr = constructContractRequest(fn, request); - JsonElement res = ContractProcess.instance.engine.executeContract(cr).result; - return gson.fromJson(res.toString(), DoipMessage.class); + if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); + if (fn != null) { + return buildRequestAndInvokeEngine(fn, request); + } + return null; } @Override public DoipMessage handleDelete(DoipMessage request) { FunctionNode fn = doipOperationsMap.get(BasicOperations.Delete.getName()); - ContractRequest cr = constructContractRequest(fn, request); - JsonElement res = ContractProcess.instance.engine.executeContract(cr).result; - return gson.fromJson(res.toString(), DoipMessage.class); + if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); + if (fn != null) { + return buildRequestAndInvokeEngine(fn, request); + } + return null; } @Override public DoipMessage handleRetrieve(DoipMessage request) { FunctionNode fn = doipOperationsMap.get(BasicOperations.Retrieve.getName()); - ContractRequest cr = constructContractRequest(fn, request); - JsonElement res = ContractProcess.instance.engine.executeContract(cr).result; - return gson.fromJson(res.toString(), DoipMessage.class); + if (fn == null) fn = doipOperationsMap.get(BasicOperations.Unknown.getName()); + if (fn != null) { + return buildRequestAndInvokeEngine(fn, request); + } + return null; + } + + public DoipMessage buildRequestAndInvokeEngine(FunctionNode fn, DoipMessage msg) { + ContractRequest contractRequest = constructContractRequest(fn, msg); + DoipMessagePacker arg = new DoipMessagePacker("doip", msg); + try { + // 改变调用的函数 + 构造DoipMessagePacker + Object ret = ContractProcess.instance.engine.executeWithoutLock(fn, contractRequest, arg); + return DOOPHandler.convertJsonElementToDoipMessage((JsonElement) ret, msg); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; } public ContractRequest constructContractRequest(FunctionNode fn, DoipMessage request) { ContractRequest cr = new ContractRequest(); cr.setContractID(""); - cr.setRequester(""); - cr.setAction(""); - cr.setArg(""); + cr.setRequester(request.credential.getSigner()); + cr.setAction(fn.functionName); return cr; } } diff --git a/src/main/java/org/bdware/sc/server/DOOPDoipServer.java b/src/main/java/org/bdware/sc/server/DOOPDoipServer.java deleted file mode 100644 index b509bc3..0000000 --- a/src/main/java/org/bdware/sc/server/DOOPDoipServer.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.bdware.sc.server; - -import org.bdware.doip.audit.EndpointConfig; -import org.bdware.doip.audit.EndpointInfo; -import org.bdware.doip.audit.client.AuditIrpClient; -import org.bdware.doip.audit.writer.ConfigurableAuditConfig; -import org.bdware.doip.endpoint.server.DoipListenerConfig; -import org.bdware.doip.endpoint.server.DoipServerImpl; -import org.bdware.doip.endpoint.server.DoipServiceInfo; -import org.bdware.doip.endpoint.server.RepositoryHandler; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import static org.bdware.doip.audit.EndpointConfig.defaultDOIPServerPort; -import static org.bdware.doip.audit.EndpointConfig.defaultRepoType; - -public class DOOPDoipServer extends DoipServerImpl { - private final ConfigurableAuditConfig auditConfig; - EndpointConfig config; - static AuditIrpClient irpClient; - - - public DOOPDoipServer(EndpointConfig config) { - super(resolveInfo(config)); - this.config = config; - this.auditConfig = irpClient.getAuditConfig(); - } - - private static DoipServiceInfo resolveInfo(EndpointConfig config) { - irpClient = new AuditIrpClient(config); - EndpointInfo info = irpClient.getEndpointInfo(); - if (info == null) { - String content = "{\"date\":\"2022-1-13\",\"name\":\"testrepoforaibd\",\"doId\":\"bdware.test.local/Repo\",\"address\":\"tcp://127.0.0.1:" + defaultDOIPServerPort + "\",\"status\":\"已审核\",\"protocol\":\"DOIP\",\"pubKey\":\"empty\",\"version\":\"2.1\"}"; - info = EndpointInfo.fromJson(content); - } - List infos = new ArrayList<>(); - try { - infos.add(new DoipListenerConfig(info.getURI(), info.getVersion())); - } catch (Exception e) { - e.printStackTrace(); - } - DoipServiceInfo ret = new DoipServiceInfo(info.getDoId(), info.getPubKey(), defaultRepoType, infos); - return ret; - } - - @Override - public void setRepositoryHandler(RepositoryHandler handler) { - Class clz = DoipServerImpl.class; - Field f = null; - try { - f = clz.getDeclaredField("requestCallback"); - f.setAccessible(true); -// f.set(this, new DOOPRequestHandler(); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/org/bdware/sc/server/DoipServerTest.java b/src/main/java/org/bdware/sc/server/DoipServerTest.java new file mode 100644 index 0000000..ff56911 --- /dev/null +++ b/src/main/java/org/bdware/sc/server/DoipServerTest.java @@ -0,0 +1,43 @@ +package org.bdware.sc.server; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.doip.endpoint.server.DoipListenerConfig; +import org.bdware.doip.endpoint.server.DoipServerImpl; +import org.bdware.doip.endpoint.server.DoipServiceInfo; +import org.bdware.sc.handler.DOOPRequestHandler; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +public class DoipServerTest { + static Logger LOGGER = LogManager.getLogger(DoipServerTest.class); + + public static void main(String[] arg) throws InterruptedException { + int port = 21042; + if (arg != null && arg.length > 0) { + port = Integer.parseInt(arg[0]); + } + run(port); + } + + public static void run(int port) throws InterruptedException { + List infos = new ArrayList<>(); + try { + infos.add(new DoipListenerConfig("tcp://127.0.0.1:" + port, "2.1")); + } catch (Exception e) { + e.printStackTrace(); + } + DoipServiceInfo info = new DoipServiceInfo("aibd.govdata.tj/do.3f9c41e6-9f8e-48a0-9220-53f438d40e43", "ownerDEF", "gateRepo", infos); + DoipServerImpl server = new DoipServerImpl(info); + final AtomicInteger count = new AtomicInteger(0); + DOOPRequestHandler handler = new DOOPRequestHandler(); + server.setRepositoryHandler(handler); + server.start(); + for (; ; ) { + LOGGER.info("Count:" + count.get()); + Thread.sleep(10000); + } + } +}