support interface

support ResultSchema
This commit is contained in:
CaiHQ 2023-06-06 17:54:57 +08:00
parent 76f564c777
commit d76f816e92
10 changed files with 132 additions and 26 deletions

View File

@ -6,7 +6,7 @@ plugins {
} }
group = "org.bdware.sc" group = "org.bdware.sc"
version = "1.8.9" version = "1.9.0"
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
// options.compilerArgs << '-Xlint:none' // options.compilerArgs << '-Xlint:none'
// options.compilerArgs << '-Xlint:deprecation' << "-Werror" // options.compilerArgs << '-Xlint:deprecation' << "-Werror"
@ -48,8 +48,8 @@ dependencies {
implementation 'com.sun.mail:javax.mail:1.6.2' implementation 'com.sun.mail:javax.mail:1.6.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'org.bdware.bdcontract:sdk-java:1.0.2' implementation 'org.bdware.bdcontract:sdk-java:1.0.2'
implementation 'org.bdware.doip:doip-audit-tool:1.2.6' implementation 'org.bdware.doip:doip-audit-tool:1.2.9'
implementation 'org.bdware.doip:doip-sdk:1.4.2' implementation 'org.bdware.doip:doip-sdk:1.4.4'
implementation fileTree(dir: 'lib', include: '*.jar') implementation fileTree(dir: 'lib', include: '*.jar')
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
} }
@ -68,7 +68,7 @@ jar {
// while develop at local use "false" // while develop at local use "false"
configurations.runtimeClasspath.filter { configurations.runtimeClasspath.filter {
it.getAbsolutePath().contains("/lib/") it.getAbsolutePath().contains("/lib/")
// false //false
}.collect { }.collect {
it.isDirectory() ? it : zipTree(it) it.isDirectory() ? it : zipTree(it)
} }

View File

@ -473,13 +473,14 @@ public class ContractProcess {
JavaScriptEntry.shardingID = JavaScriptEntry.shardingID =
this.contract.getShardingId(); // 设置javaScriptEntry中的shardingID this.contract.getShardingId(); // 设置javaScriptEntry中的shardingID
// JavaScriptEntry // JavaScriptEntry
// contract.getCreateParam().get("repoId").getAsString()-->去获取repoId
//知道自己的BDOID --> repo的id+contract.getID()
String zipPath = contract.getScriptStr(); String zipPath = contract.getScriptStr();
if (isArchiveFile(new File(zipPath))) { if (isArchiveFile(new File(zipPath))) {
ZipFile zf = new ZipFile(zipPath); ZipFile zf = new ZipFile(zipPath);
ContractZipBundle zipBundle = new YJSCompiler().compile(zf); ContractZipBundle zipBundle = new YJSCompiler().compile(zf);
cn = zipBundle.mergeContractNode(); cn = zipBundle.mergeContractNode();
// check functionNodes // check functionNodes
List<FunctionNode> functionNodes = cn.getFunctions();
injectHandlers(); injectHandlers();
this.contract.setYjsType(cn.getYjsType()); this.contract.setYjsType(cn.getYjsType());
@ -569,6 +570,7 @@ public class ContractProcess {
fun.appendBeforeInvokeHandler(argSchemaHandler); fun.appendBeforeInvokeHandler(argSchemaHandler);
} }
if (fun.isExport()) { if (fun.isExport()) {
//if(fun.annotations...) //if(fun.annotations...)
AccessHandler accessHandler = createHandlerIfExist(fun, AccessHandler.class); AccessHandler accessHandler = createHandlerIfExist(fun, AccessHandler.class);
@ -576,6 +578,10 @@ public class ContractProcess {
fun.appendBeforeInvokeHandler(accessHandler); fun.appendBeforeInvokeHandler(accessHandler);
} }
fun.appendAfterInvokeHandler(new ObjToJsonHandler()); fun.appendAfterInvokeHandler(new ObjToJsonHandler());
ResultSchemaHandler resultSchemaHandler = createHandlerIfExist(fun, ResultSchemaHandler.class);
if (resultSchemaHandler != null) {
fun.appendAfterInvokeHandler(resultSchemaHandler);
}
// fun.appendBeforeInvokeHandler(new ReadMeHandler()); // fun.appendBeforeInvokeHandler(new ReadMeHandler());
// Mask是用于返回真正结果之后做一些偏移以保护数据隐私 // Mask是用于返回真正结果之后做一些偏移以保护数据隐私
// if (fun.isMask()) { // if (fun.isMask()) {
@ -584,7 +590,7 @@ public class ContractProcess {
// engine.getResources().loadAsString("/maskConfig.json"); // engine.getResources().loadAsString("/maskConfig.json");
// System.out.println("injectMask"+maskConfig); // System.out.println("injectMask"+maskConfig);
// System.out.println("injectMask"+this.contract.Mask); // System.out.println("injectMask"+this.contract.Mask);
fun.appendAfterInvokeHandler(new MaskHandler()); // fun.appendAfterInvokeHandler(new MaskHandler());
// } // }
} }
if (fun.isHomomorphicEncrypt()) { if (fun.isHomomorphicEncrypt()) {
@ -728,7 +734,7 @@ public class ContractProcess {
startPort = arg.getAsJsonObject().get("doipStartPort").getAsInt(); startPort = arg.getAsJsonObject().get("doipStartPort").getAsInt();
} }
LOGGER.info("Fetch the onStartingDoipServerRes from router successfully, the result is " + onStartingDoipServerRes); 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); returnValue.addProperty("doipListenPort", doipListenPort);
this.contract.setDoipPort(doipListenPort); this.contract.setDoipPort(doipListenPort);
returnValue.addProperty("doipStartPort", startPort); returnValue.addProperty("doipStartPort", startPort);

View File

@ -5,13 +5,11 @@ import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.DiagnosticErrorListener; import org.antlr.v4.runtime.DiagnosticErrorListener;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bdware.doip.audit.EndpointConfig;
import org.bdware.sc.engine.YJSFilter; import org.bdware.sc.engine.YJSFilter;
import org.bdware.sc.node.*; import org.bdware.sc.node.*;
import org.bdware.sc.parser.JavaScriptLexer; import org.bdware.sc.parser.JavaScriptLexer;
import org.bdware.sc.parser.YJSParser; import org.bdware.sc.parser.YJSParser;
import org.bdware.sc.parser.YJSParser.ProgramContext; import org.bdware.sc.parser.YJSParser.ProgramContext;
import org.bdware.sc.server.DoipClusterServer;
import org.bdware.sc.util.JsonUtil; import org.bdware.sc.util.JsonUtil;
import org.bdware.sc.visitor.ContractReader; import org.bdware.sc.visitor.ContractReader;
import wrp.jdk.nashorn.internal.objects.Global; import wrp.jdk.nashorn.internal.objects.Global;
@ -23,6 +21,7 @@ import wrp.jdk.nashorn.internal.runtime.options.Options;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -127,12 +126,18 @@ public class YJSCompiler {
Set<String> toParse = new HashSet<>(); Set<String> toParse = new HashSet<>();
toParse.add(cm.main); toParse.add(cm.main);
Set<String> todo = new HashSet<>(); Set<String> todo = new HashSet<>();
Set<String> allEntries = new HashSet<>();
Enumeration<? extends ZipEntry> iter = zf.entries();
for (; iter.hasMoreElements(); ) {
ZipEntry ele = iter.nextElement();
if (ele != null)
allEntries.add(ele.getName());
}
while (toParse.size() > 0) { while (toParse.size() > 0) {
for (String str : toParse) { for (String str : toParse) {
if (czb.containsPath(str)) { if (czb.containsPath(str)) {
continue; continue;
} }
ZipEntry entry = zf.getEntry(str.startsWith("/") ? str : "/" + str); ZipEntry entry = zf.getEntry(str.startsWith("/") ? str : "/" + str);
if (null == entry) { if (null == entry) {
throw new IllegalStateException("missing import:" + str); throw new IllegalStateException("missing import:" + str);
@ -140,7 +145,9 @@ public class YJSCompiler {
ContractNode cn = compile(zf.getInputStream(entry), str); ContractNode cn = compile(zf.getInputStream(entry), str);
czb.put(str, cn); czb.put(str, cn);
for (ImportNode in : cn.getImports()) { 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(); toParse.clear();
@ -173,7 +180,9 @@ public class YJSCompiler {
compile(new ByteArrayInputStream(globalBeanContract.getBytes(StandardCharsets.UTF_8)), compile(new ByteArrayInputStream(globalBeanContract.getBytes(StandardCharsets.UTF_8)),
globalBeanName + ".yjs")); globalBeanName + ".yjs"));
LOGGER.info("--compile-- " + globalBeanName); LOGGER.info("--compile-- " + globalBeanName);
czb.setMergedContractNode();
ContractNode node = czb.mergeContractNode();
handleFunctionAnnotation(node);
return czb; return czb;
} }
@ -193,17 +202,22 @@ public class YJSCompiler {
contract = reader.visitProgram(tree); contract = reader.visitProgram(tree);
// 遍历完 获取 contract 里的 yjs type // 遍历完 获取 contract 里的 yjs type
contract.initPlainText(cts); contract.initPlainText(cts);
handleAnnotation(contract);//处理注解 handleModuleAnnotation(contract);//处理注解
handleFunctionAnnotation(contract);
return contract; return contract;
} }
private void handleAnnotation(ContractNode contractNode) throws Exception { private void handleModuleAnnotation(ContractNode contractNode) throws Exception {
for (AnnotationNode node : contract.annotations) { for (AnnotationNode node : contract.annotations) {
AnnotationProcessor processor = findProcessor(node); AnnotationProcessor processor = findProcessor(node);
if (processor != null) { if (processor != null) {
processor.processContract(node, contractNode); processor.processContract(node, contractNode);
} }
} }
}
private void handleFunctionAnnotation(ContractNode contractNode) throws Exception {
for (FunctionNode functionNode : contractNode.getFunctions()) { for (FunctionNode functionNode : contractNode.getFunctions()) {
List<AnnotationNode> annos = functionNode.annotations;//函数里的annotation List<AnnotationNode> annos = functionNode.annotations;//函数里的annotation
if (annos != null) if (annos != null)
@ -215,7 +229,7 @@ public class YJSCompiler {
} }
} }
private AnnotationProcessor findProcessor(AnnotationNode node) { public static AnnotationProcessor findProcessor(AnnotationNode node) {
try { try {
String clzName = YJSCompiler.class.getPackage().getName(); String clzName = YJSCompiler.class.getPackage().getName();
clzName += ".ap." + node.getType(); clzName += ".ap." + node.getType();

View File

@ -65,6 +65,7 @@ public class ArgSchemaHandler implements AnnotationHook {
JsonObject jo = new JsonObject(); JsonObject jo = new JsonObject();
jo.addProperty("msg", visitor.getException()); jo.addProperty("msg", visitor.getException());
jo.addProperty("code", visitor.errorCode); jo.addProperty("code", visitor.errorCode);
jo.add("argSchema",JsonParser.parseString(a.getArgs().get(0)));
throw new ScriptReturnException(jo); throw new ScriptReturnException(jo);
} }
return argPacks; return argPacks;

View File

@ -1,9 +1,6 @@
package org.bdware.sc.engine.hook; package org.bdware.sc.engine.hook;
import com.google.gson.JsonArray; import com.google.gson.*;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.bdware.mockjava.JsonVisitor; import org.bdware.mockjava.JsonVisitor;
public class ArgSchemaVisitor extends JsonVisitor { public class ArgSchemaVisitor extends JsonVisitor {
@ -37,12 +34,12 @@ public class ArgSchemaVisitor extends JsonVisitor {
} }
status &= visitor.status; status &= visitor.status;
} else { } else {
message += "[Missing argument] " + key.substring(1) + " should be supplied "; message += "[Missing key] " + key.substring(1) + " should be supplied ";
status = false; status = false;
errorCode = 1002; errorCode = 1002;
} }
} else { } 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)); ArgSchemaVisitor visitor = new ArgSchemaVisitor(jo.get(key));
visitor.visit(schema.get(key)); visitor.visit(schema.get(key));
if (!visitor.status) { if (!visitor.status) {

View File

@ -43,8 +43,10 @@ public class DOOPAfterExecHandler implements AnnotationHook {
if (!(argPacks.ret instanceof DoipMessage)) { if (!(argPacks.ret instanceof DoipMessage)) {
JsonObject jsonObjectRes = ((JsonElement) argPacks.ret).getAsJsonObject(); JsonObject jsonObjectRes = ((JsonElement) argPacks.ret).getAsJsonObject();
if (!jsonObjectRes.has("bodyBase64Encoded") || jsonObjectRes.get("bodyBase64Encoded").getAsBoolean() == false) { if (!jsonObjectRes.has("bodyBase64Encoded") || jsonObjectRes.get("bodyBase64Encoded").getAsBoolean() == false) {
String body = jsonObjectRes.get("body").getAsString(); if (jsonObjectRes.has("body")) {
jsonObjectRes.addProperty("body", ByteUtil.encodeBASE64(body.getBytes(StandardCharsets.UTF_8))); String body = jsonObjectRes.get("body").getAsString();
jsonObjectRes.addProperty("body", ByteUtil.encodeBASE64(body.getBytes(StandardCharsets.UTF_8)));
}
} }
// validate json response // validate json response
ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonObjectRes); ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonObjectRes);
@ -69,7 +71,7 @@ public class DOOPAfterExecHandler implements AnnotationHook {
case Search: case Search:
case ListOps: case ListOps:
case Delete: case Delete:
return JsonParser.parseString("{\"!header\":{\"!response\":\"string\",\"attributes\":{}},\"body\":\"string\"}"); return JsonParser.parseString("{\"header\":{\"response\":\"string\",\"attributes\":{}},\"body\":\"string\"}");
case Extension: case Extension:
case Unknown: case Unknown:
default: default:

View File

@ -38,6 +38,7 @@ public class DOOPBeforeExecHandler implements AnnotationHook {
// set doipMsgPackerArg struct's params // set doipMsgPackerArg struct's params
doipMsgPackerArg.setSource("http"); doipMsgPackerArg.setSource("http");
doipMsgPackerArg.rawDoipMsg = convertHttpRequestToDoipMessage(httpReq); doipMsgPackerArg.rawDoipMsg = convertHttpRequestToDoipMessage(httpReq);
if (httpReq.verifySignature()) { if (httpReq.verifySignature()) {
doipMsgPackerArg.rawDoipMsg.credential = new MessageCredential(httpReq.getRequester(), new byte[0]); doipMsgPackerArg.rawDoipMsg.credential = new MessageCredential(httpReq.getRequester(), new byte[0]);
} else { } else {

View File

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

View File

@ -92,9 +92,9 @@ public class DOOPRequestHandler implements DoipRequestHandler {
DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder(); DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
builder.createResponse(DoipResponseCode.Declined, msg); builder.createResponse(DoipResponseCode.Declined, msg);
builder.setBody(bo.toByteArray()); 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"); logger.error("buildRequestAndInvokeEngine has something wrong, executeWithoutLock err or validateJsonElementRulesByArgSchemaVisitor err");
return message; return builder.create();
} }
} }

View File

@ -212,6 +212,7 @@ public class MemoryDump implements Serializable {
break; break;
case String: case String:
case Int: case Int:
case Boolean:
obj = mo.data; obj = mo.data;
break; break;
case Double: case Double: