diff --git a/src/main/java/org/bdware/sc/ContractProcess.java b/src/main/java/org/bdware/sc/ContractProcess.java index c0173e9..05e8799 100644 --- a/src/main/java/org/bdware/sc/ContractProcess.java +++ b/src/main/java/org/bdware/sc/ContractProcess.java @@ -1,5 +1,6 @@ package org.bdware.sc; +import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; @@ -45,6 +46,7 @@ import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptException; import java.io.*; +import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*; @@ -556,7 +558,14 @@ public class ContractProcess { if (fun.isConfidential()) { fun.appendBeforeInvokeHandler(new ConfidentialHandler(fun)); } + + ArgSchemaHandler argSchemaHandler = createHandlerIfExist(fun,fun.annotations,ArgSchemaHandler.class); + if(argSchemaHandler!=null){ + fun.appendBeforeInvokeHandler(argSchemaHandler); + } + if (fun.isExport()) { + //if(fun.annotations...) fun.appendAfterInvokeHandler(new ObjToJsonHandler()); // fun.appendBeforeInvokeHandler(new ReadMeHandler()); // Mask是用于返回真正结果之后,做一些偏移,以保护数据隐私。 @@ -576,9 +585,28 @@ public class ContractProcess { if (fun.isHomomorphicDecrypt()) { fun.appendAfterInvokeHandler(new HomomorphicDecryptHandler(fun)); } + } } + T createHandlerIfExist(FunctionNode function,List annotations, Class clz) { + YJSAnnotation annotation = clz.getAnnotation(YJSAnnotation.class); + if (annotation==null) return null; + if (annotations==null) return null; + for (AnnotationNode node: annotations){ + if (annotation.name().equals(node.getType())){ + try { + Method m = clz.getDeclaredMethod("fromAnnotationNode",FunctionNode.class,AnnotationNode.class); + T result = (T) m.invoke(null,function, node); + return result; + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return null; + } + public String changeDumpPeriod(String period) { System.out.println("[ContractProcess] period" + period); diff --git a/src/main/java/org/bdware/sc/engine/DesktopEngine.java b/src/main/java/org/bdware/sc/engine/DesktopEngine.java index a1da6a9..26f295c 100644 --- a/src/main/java/org/bdware/sc/engine/DesktopEngine.java +++ b/src/main/java/org/bdware/sc/engine/DesktopEngine.java @@ -294,6 +294,8 @@ public class DesktopEngine extends JSEngine { } ScriptObjectMirror globalVars = (ScriptObjectMirror) engine.get("Global"); ConfidentialContractUtil.generateConfidentialContract(cn, globalVars, global); + Context.setGlobal(global); + ContractResult cResult = new ContractResult(Status.Success, new JsonPrimitive(contract.getPublicKey())); cResult.isInsnLimit = isInsnLimit; @@ -426,6 +428,11 @@ public class DesktopEngine extends JSEngine { @Override public synchronized ContractResult executeContract(ContractRequest input) { + Global oldGlobal = Context.getGlobal(); + boolean globalChanged = (oldGlobal != global); + if (globalChanged) { + Context.setGlobal(global); + } ContractProcess.Logger previous = this.getTracePS(); ByteArrayOutputStream bo = null; if (syncUtil.startFlag && syncUtil.currType == SyncType.Trace && !recovering) { @@ -580,7 +587,9 @@ public class DesktopEngine extends JSEngine { } } finally { this.redirectTracePS(previous); + if (globalChanged) Context.setGlobal(oldGlobal); } + } 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 9c65aff..8ba4f1f 100644 --- a/src/main/java/org/bdware/sc/engine/JSONTool.java +++ b/src/main/java/org/bdware/sc/engine/JSONTool.java @@ -1,15 +1,14 @@ package org.bdware.sc.engine; import com.google.gson.*; +import jdk.nashorn.internal.runtime.Context; import wrp.jdk.nashorn.api.scripting.ScriptObjectMirror; import wrp.jdk.nashorn.internal.objects.NativeArray; import wrp.jdk.nashorn.internal.runtime.PropertyMap; +import wrp.jdk.nashorn.internal.runtime.ScriptObject; import wrp.jdk.nashorn.internal.scripts.JO; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class JSONTool { public static JsonElement convertMirrorToJson(Object ret2) { diff --git a/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java new file mode 100644 index 0000000..6623486 --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java @@ -0,0 +1,63 @@ +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.sc.ContractProcess; +import org.bdware.sc.JSEngine; +import org.bdware.sc.bean.ContractRequest; +import org.bdware.sc.bean.ProjectConfig; +import org.bdware.sc.boundry.ScriptReturnException; +import org.bdware.sc.engine.DesktopEngine; +import org.bdware.sc.node.AnnotationHook; +import org.bdware.sc.node.AnnotationNode; +import org.bdware.sc.node.FunctionNode; + +@YJSAnnotation(name = "ArgSchema") +public class ArgSchemaHandler implements AnnotationHook { + private AnnotationNode a; + private static final Logger LOGGER = LogManager.getLogger(ArgSchemaHandler.class); + public ArgSchemaHandler(AnnotationNode annoNode){ + a=annoNode; + String arg = a.getArgs().get(0); + +// if (arg.startsWith("/")){ +// ;//ContractProcess.instance.engine.getResources().loadAsString(arg); +// }else { +// ; +// } + } + public static ArgSchemaHandler fromAnnotationNode(FunctionNode funNode, AnnotationNode annoNode){ + //a= annoNode; + return new ArgSchemaHandler(annoNode); + } + @Override + public Object handle(ContractRequest input, JSEngine Engine, Object ret) throws ScriptReturnException { + //input.getArg(); + DesktopEngine desktopEngine = (DesktopEngine) Engine; + ArgSchemaVisitor visitor = new ArgSchemaVisitor(JsonParser.parseString(input.getArg().getAsString())); + + + System.out.println(JsonParser.parseString(input.getArg().getAsString())); + System.out.println(JsonParser.parseString(a.getArgs().get(0))); + + if(input.getArg().getAsString().isEmpty()&&!a.getArgs().get(0).equals("")){ + JsonObject jo = new JsonObject(); + jo.addProperty("msg", "[Empty argument] argument should not be empty"); + jo.addProperty("code", 1003); + //jo.add("code":); + 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("code":); + throw new ScriptReturnException(jo); + } + return ret; + } +} diff --git a/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java new file mode 100644 index 0000000..8fd84b0 --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java @@ -0,0 +1,166 @@ +package org.bdware.sc.engine.hook; + +import com.alibaba.datax.transport.transformer.maskingMethods.cryptology.AESEncryptionImpl; +import com.alibaba.datax.transport.transformer.maskingMethods.cryptology.FormatPreservingEncryptionImpl; +import com.alibaba.datax.transport.transformer.maskingMethods.differentialPrivacy.EpsilonDifferentialPrivacyImpl; +import com.alibaba.datax.transport.transformer.maskingMethods.irreversibleInterference.MD5EncryptionImpl; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.bdware.mockjava.JsonVisitor; + +public class ArgSchemaVisitor extends JsonVisitor { + JsonElement root; + public boolean status=true; + public int errorCode=0; + //{"msg":"xxx","code":1000} + // +// JsonElement message = new JsonPrimitive(""); + public String message=""; + + public ArgSchemaVisitor(JsonElement ret) { + root = ret; + } + + @Override + public JsonVisitor visitObject(JsonObject schema) { + //message = new JsonObject(); + if (root.isJsonObject()) { + JsonObject jo = root.getAsJsonObject(); + for (String key : schema.keySet()) { + if (key.startsWith("!")) { + //TODO + //if(必選) + if(jo.has(key.substring(1))){ + ArgSchemaVisitor visitor = new ArgSchemaVisitor(jo.get(key.substring(1))); + visitor.visit(schema.get(key)); + jo.add(key, visitor.get()); + if (!visitor.status){ + errorCode+=visitor.errorCode; + message+=visitor.message; + } + status&=visitor.status; + + } + else{ + message+="[Missing argument] "+key.substring(1)+" should be supplied "; + status = false; + errorCode=1002; + } + } + else{ + if(jo.has(key)){ + ArgSchemaVisitor visitor = new ArgSchemaVisitor(jo.get(key)); + visitor.visit(schema.get(key)); + jo.add(key, visitor.get()); + if (!visitor.status){ + message+=visitor.message; + errorCode+=visitor.errorCode; + } + status&=visitor.status; + + } + } + } + } + return this; + } + + @Override + public JsonVisitor visitJsonArray(JsonArray ele) { + if (root.isJsonArray()) { + JsonArray array = root.getAsJsonArray(); + //message = new JsonArray(); + + for (int i = 0; i < array.size(); i++) { + ArgSchemaVisitor visitor = new ArgSchemaVisitor(array.get(i)); + visitor.visit(ele.get(0)); + message+=visitor.message; + } + } + return this; + } + + public JsonElement get() { + return root; + } + + @Override + + public JsonVisitor visitPrimitive(JsonPrimitive primitive) { + // + if (primitive.isString()) { + String type = primitive.getAsString(); + try { + String result = ""; + //md5不需要参数 + if (type.equals("string")) { + if (root.isJsonPrimitive()&& root.getAsJsonPrimitive().isString()){ + return this; + }else{ +// message=new JsonObject(); +// message.getAsJsonObject().addProperty("msg","xxx"); +// message.getAsJsonObject().addProperty("code","1000"); + message="[Type error] The value ("+root.getAsJsonPrimitive().getAsString() +") should be string"; + status = false; + errorCode=1001; + return this; + } + } else if (type.equals("number")) { + if (root.isJsonPrimitive() && root.getAsJsonPrimitive().isNumber()) { + return this; + } else { + message="[Type error] The value ("+root.getAsJsonPrimitive().getAsString() +") should be number"; + status = false; + errorCode=1001; + return this; + } + } + else if (type.equals("boolean")) { + if (root.isJsonPrimitive() && root.getAsJsonPrimitive().isBoolean()) { + return this; + } else { + message="[Type error] The value ("+root.getAsJsonPrimitive().getAsString() +") should be boolean"; + status = false; + errorCode=1001; + return this; + } + } + else if (type.equals("[]")) { + if (root.isJsonArray()) { + return this; + } else { + message="[Type error] The value ("+root.getAsJsonPrimitive().getAsString() +") should be array"; + status = false; + errorCode=1001; + return this; + } + } + else if (type.equals("{}")) { + if (root.isJsonObject()) { + return this; + } else { + message="[Type error] The value ("+root.getAsJsonPrimitive().getAsString() +") should be object"; + status = false; + errorCode=1001; + return this; + } + } + + } catch (Exception e) { + System.out.println(e); + } + } + + //String result = masker.execute(primitive.toString()); + //System.out.println(result); + + //root = new JsonPrimitive(root.getAsString().substring(0, 2)); + //https://github.com/guohf/DataX-Masking + return this; + } + public boolean getStatus(){return status;} + + public String getException() {return message;} +} diff --git a/src/main/java/org/bdware/sc/engine/hook/YJSAnnotation.java b/src/main/java/org/bdware/sc/engine/hook/YJSAnnotation.java new file mode 100644 index 0000000..6931073 --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/YJSAnnotation.java @@ -0,0 +1,9 @@ +package org.bdware.sc.engine.hook; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface YJSAnnotation { + String name() default ""; +} diff --git a/src/test/java/org/bdware/sc/engine/hook/test/ArgSchemaTest.java b/src/test/java/org/bdware/sc/engine/hook/test/ArgSchemaTest.java new file mode 100644 index 0000000..9118950 --- /dev/null +++ b/src/test/java/org/bdware/sc/engine/hook/test/ArgSchemaTest.java @@ -0,0 +1,57 @@ +package org.bdware.sc.engine.hook.test; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.bdware.sc.engine.hook.ArgSchemaVisitor; +import org.junit.Test; + +public class ArgSchemaTest { + @Test + public void test1(){ + JsonObject realData=JsonParser.parseString("{\"data\":[{\"name\":\"zzz\"},{\"name\":\"aaa\"}],\"doId\":1}").getAsJsonObject(); + JsonObject schema=JsonParser.parseString("{\"data\":[{\"name\":\"string\"}],\"doId\":\"number\"}").getAsJsonObject(); + + + ArgSchemaVisitor visitor=new ArgSchemaVisitor(realData); + visitor.visit(schema); + System.out.println(visitor.getStatus()); + System.out.println(visitor.getException().toString()); + } + @Test + public void test2(){ + JsonObject realData=JsonParser.parseString("{\"data\":[{\"name\":\"zzz\"},{\"name\":\"aaa\"}],\"doId\":\"string\"}").getAsJsonObject(); + JsonObject schema=JsonParser.parseString("{\"data\":[{\"name\":\"string\"}],\"doId\":\"number\"}").getAsJsonObject(); + + + ArgSchemaVisitor visitor=new ArgSchemaVisitor(realData); + visitor.visit(schema); + System.out.println(visitor.getStatus()); + System.out.println(visitor.getException().toString()); + System.out.println(visitor.errorCode); + } + @Test + public void test3(){ + JsonElement realData=JsonParser.parseString("data.json"); + JsonElement schema=JsonParser.parseString("\"string\""); + + + ArgSchemaVisitor visitor=new ArgSchemaVisitor(realData); + visitor.visit(schema); + System.out.println(visitor.getStatus()); + System.out.println(visitor.getException().toString()); + System.out.println(visitor.errorCode); + } + + //缺少必选项 + @Test + public void test4(){ + JsonObject realData=JsonParser.parseString("{\"data\":[{\"name\":\"zzz\"},{\"name\":\"aaa\"}]}").getAsJsonObject(); + JsonObject schema=JsonParser.parseString("{\"data\":[{\"name\":\"string\"}],\"!doId\":\"string\"}").getAsJsonObject(); + ArgSchemaVisitor visitor=new ArgSchemaVisitor(realData); + visitor.visit(schema); + System.out.println(visitor.getStatus()); + System.out.println(visitor.getException()); + System.out.println(visitor.errorCode); + } +}