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"
version = "1.8.9"
version = "1.9.0"
tasks.withType(JavaCompile) {
// options.compilerArgs << '-Xlint:none'
// options.compilerArgs << '-Xlint:deprecation' << "-Werror"
@ -48,8 +48,8 @@ dependencies {
implementation 'com.sun.mail:javax.mail:1.6.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'org.bdware.bdcontract:sdk-java:1.0.2'
implementation 'org.bdware.doip:doip-audit-tool:1.2.6'
implementation 'org.bdware.doip:doip-sdk:1.4.2'
implementation 'org.bdware.doip:doip-audit-tool:1.2.9'
implementation 'org.bdware.doip:doip-sdk:1.4.4'
implementation fileTree(dir: 'lib', include: '*.jar')
testImplementation 'junit:junit:4.13.2'
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -38,6 +38,7 @@ public class DOOPBeforeExecHandler implements AnnotationHook {
// set doipMsgPackerArg struct's params
doipMsgPackerArg.setSource("http");
doipMsgPackerArg.rawDoipMsg = convertHttpRequestToDoipMessage(httpReq);
if (httpReq.verifySignature()) {
doipMsgPackerArg.rawDoipMsg.credential = new MessageCredential(httpReq.getRequester(), new byte[0]);
} 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();
builder.createResponse(DoipResponseCode.Declined, msg);
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");
return message;
return builder.create();
}
}

View File

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