From 2cf6886649c0acc749ad732680d1503c5e32f7c5 Mon Sep 17 00:00:00 2001 From: CaiHQ Date: Fri, 24 Sep 2021 13:31:17 +0800 Subject: [PATCH] initial commit --- .gitignore | 1 + build.gradle | 33 +++ .../src/org/bdware/server/ByteHexUtil.java | 52 ++++ src/main/src/org/bdware/server/CMDConf.java | 108 ++++++++ src/main/src/org/bdware/server/Entry.java | 99 ++++++++ .../src/org/bdware/server/action/Action.java | 20 ++ .../bdware/server/action/ActionExecutor.java | 173 +++++++++++++ .../server/action/HttpResultCallback.java | 83 +++++++ .../src/org/bdware/server/action/Result.java | 16 ++ .../org/bdware/server/action/SyncResult.java | 126 ++++++++++ .../server/http/FileDownloaderCallback.java | 61 +++++ .../server/http/HttpFileHandleAdapter.java | 157 ++++++++++++ .../org/bdware/server/http/HttpMethod.java | 36 +++ .../org/bdware/server/http/URIHandler.java | 113 +++++++++ .../src/org/bdware/server/http/URIPath.java | 13 + .../bdware/server/nodecenter/Response.java | 9 + .../bdware/server/nodecenter/ResultBack.java | 14 ++ .../bdware/server/nodecenter/UserMySQL.java | 5 + .../server/nodecenter/client/CMNodeBean.java | 85 +++++++ .../bdware/server/permission/Permission.java | 93 +++++++ .../org/bdware/server/permission/Role.java | 43 ++++ .../server/ws/DelimiterBasedFrameEncoder.java | 17 ++ .../org/bdware/server/ws/DelimiterCodec.java | 17 ++ .../server/ws/WebSocketIndexPageHandler.java | 100 ++++++++ .../server/ws/WebSocketServerIndexPage.java | 105 ++++++++ src/main/src/resources/log4j.properties | 8 + .../org/bdware/server/IndexServer.java | 60 +++++ .../org/bdware/server/action/IndexAction.java | 230 ++++++++++++++++++ .../bdware/server/http/IndexHttpHandler.java | 157 ++++++++++++ .../bdware/server/http/URIHandlerTest.java | 49 ++++ .../permission/test/PermissionTest.java | 91 +++++++ .../bdware/server/test/BDLedgerClient.java | 84 +++++++ .../bdware/server/test/ByteHexUtilTest.java | 14 ++ .../org/bdware/server/test/CMHttpTest.java | 96 ++++++++ .../org/bdware/server/test/GsonParseTest.java | 21 ++ .../bdware/server/test/HttpPostFormTest.java | 111 +++++++++ .../org/bdware/server/test/LongParseTest.java | 8 + .../org/bdware/server/test/NCHttpTest.java | 84 +++++++ .../org/bdware/server/test/StringTest.java | 19 ++ 39 files changed, 2611 insertions(+) create mode 100644 build.gradle create mode 100644 src/main/src/org/bdware/server/ByteHexUtil.java create mode 100644 src/main/src/org/bdware/server/CMDConf.java create mode 100644 src/main/src/org/bdware/server/Entry.java create mode 100644 src/main/src/org/bdware/server/action/Action.java create mode 100644 src/main/src/org/bdware/server/action/ActionExecutor.java create mode 100644 src/main/src/org/bdware/server/action/HttpResultCallback.java create mode 100644 src/main/src/org/bdware/server/action/Result.java create mode 100644 src/main/src/org/bdware/server/action/SyncResult.java create mode 100644 src/main/src/org/bdware/server/http/FileDownloaderCallback.java create mode 100644 src/main/src/org/bdware/server/http/HttpFileHandleAdapter.java create mode 100644 src/main/src/org/bdware/server/http/HttpMethod.java create mode 100644 src/main/src/org/bdware/server/http/URIHandler.java create mode 100644 src/main/src/org/bdware/server/http/URIPath.java create mode 100644 src/main/src/org/bdware/server/nodecenter/Response.java create mode 100644 src/main/src/org/bdware/server/nodecenter/ResultBack.java create mode 100644 src/main/src/org/bdware/server/nodecenter/UserMySQL.java create mode 100644 src/main/src/org/bdware/server/nodecenter/client/CMNodeBean.java create mode 100644 src/main/src/org/bdware/server/permission/Permission.java create mode 100644 src/main/src/org/bdware/server/permission/Role.java create mode 100644 src/main/src/org/bdware/server/ws/DelimiterBasedFrameEncoder.java create mode 100644 src/main/src/org/bdware/server/ws/DelimiterCodec.java create mode 100644 src/main/src/org/bdware/server/ws/WebSocketIndexPageHandler.java create mode 100644 src/main/src/org/bdware/server/ws/WebSocketServerIndexPage.java create mode 100644 src/main/src/resources/log4j.properties create mode 100644 src/main/thirdparty/org/bdware/server/IndexServer.java create mode 100644 src/main/thirdparty/org/bdware/server/action/IndexAction.java create mode 100644 src/main/thirdparty/org/bdware/server/http/IndexHttpHandler.java create mode 100644 src/test/java/org/bdware/server/http/URIHandlerTest.java create mode 100644 src/test/java/org/bdware/server/permission/test/PermissionTest.java create mode 100644 src/test/java/org/bdware/server/test/BDLedgerClient.java create mode 100644 src/test/java/org/bdware/server/test/ByteHexUtilTest.java create mode 100644 src/test/java/org/bdware/server/test/CMHttpTest.java create mode 100644 src/test/java/org/bdware/server/test/GsonParseTest.java create mode 100644 src/test/java/org/bdware/server/test/HttpPostFormTest.java create mode 100644 src/test/java/org/bdware/server/test/LongParseTest.java create mode 100644 src/test/java/org/bdware/server/test/NCHttpTest.java create mode 100644 src/test/java/org/bdware/server/test/StringTest.java diff --git a/.gitignore b/.gitignore index a1c2a23..d2fa3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/build # Compiled class file *.class diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..0292d37 --- /dev/null +++ b/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java' + id 'java-library' +} + +sourceSets { + main { + java { + srcDirs 'src/main/src', 'src/main/thirdparty', 'src/main/test' + } + resources { + srcDir 'src/main/resources' + } + } + test { + java { + srcDir 'src/test/java' + } + resources { + srcDir 'src/test/resources' + } + } +} +dependencies { + api project (":common") + api 'io.netty:netty-all:4.1.52.Final' + api 'io.netty:netty-tcnative-boringssl-static:2.0.41.Final' + api 'org.apache.logging.log4j:log4j-core:2.14.1' + api 'org.apache.logging.log4j:log4j-api:2.14.1' + api 'com.google.code.gson:gson:2.8.8' + + testImplementation 'junit:junit:4.13.2' +} diff --git a/src/main/src/org/bdware/server/ByteHexUtil.java b/src/main/src/org/bdware/server/ByteHexUtil.java new file mode 100644 index 0000000..60fe3a5 --- /dev/null +++ b/src/main/src/org/bdware/server/ByteHexUtil.java @@ -0,0 +1,52 @@ +package org.bdware.server; + +public class ByteHexUtil { + protected static final char[] hexArray = "0123456789ABCDEF".toCharArray(); + // lower ascii only + private static final int[] HEX_TO_INT = + new int[]{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32-47 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48-63 + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64-79 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80-95 + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96-111 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 111-127 + }; + + public static byte[] decode(String s) { + char[] c = s.toCharArray(); + int len = c.length; + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) (((HEX_TO_INT[(int) c[i]]) << 4) + HEX_TO_INT[(int) c[i + 1]]); + } + return data; + } + + public static String encode(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + int v; + for (int j = 0; j < bytes.length; j++) { + v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + public static String byteArrayToHexString(byte[] byteArray) { + if (byteArray == null) { + return null; + } + char[] hexArray = "0123456789ABCDEF".toCharArray(); + char[] hexChars = new char[byteArray.length * 2]; + for (int j = 0; j < byteArray.length; j++) { + int v = byteArray[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } +} diff --git a/src/main/src/org/bdware/server/CMDConf.java b/src/main/src/org/bdware/server/CMDConf.java new file mode 100644 index 0000000..322386e --- /dev/null +++ b/src/main/src/org/bdware/server/CMDConf.java @@ -0,0 +1,108 @@ +package org.bdware.server; + +import com.google.gson.Gson; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.*; +import java.lang.reflect.Field; + +/** + * Used to represent configurations from cmd + * + * @author Kaidong Wu + */ +public class CMDConf { + private static final Logger LOGGER = LogManager.getLogger(CMDConf.class); + + public String cmi = ""; + public String debug = ""; + public boolean disableDoRepo = false; + public boolean disableLocalLhs = false; + public String doipCertPath = ""; + public String doipLhsAddress = ""; + public int doipPort = -1; + public String doipUserHandle = ""; + public boolean enableEventPersistence = false; + public String enableSsl = "./ssl/chained.pem:./ssl/domain.pem"; + public String ip = "127.0.0.1"; + public boolean isLAN = true; + public boolean overwrite = false; + public int servicePort = 18005; + public String textFileSuffixes = ".yjs,.json,.txt,.css,.js,.html,.md,.conf,.csv"; + // BDLedger可执行文件,若在服务器上运行请使用bdledger_linux + public String withBdledgerClient = "./runnable/bdledger_mac"; + public boolean withBdledgerServer = false; + + public static CMDConf parseConf(String confPath) { + CMDConf ret = null; + File conf = new File(confPath); + if (conf.exists()) { + try (BufferedReader br = new BufferedReader(new FileReader(conf))) { + StringBuilder sbl = new StringBuilder(); + String temp; + while (null != (temp = br.readLine())) { + sbl.append(temp); + } + ret = new Gson().fromJson(sbl.toString(), CMDConf.class); + } catch (IOException ignored) { + LOGGER.warn("parsing configure from file failed!"); + } + } + if (null == ret) { + LOGGER.warn("use default configure"); + return new CMDConf(); + } + return ret; + } + + public CMDConf parseArgs(String[] args) { + for (String arg : args) { + if (null == arg || !arg.startsWith("-")) { + continue; + } + String[] cmdArg = arg.split("="); + String[] cmdArgName = cmdArg[0].substring(1).split("-"); + StringBuilder sbl = new StringBuilder(cmdArgName[0]); + for (int i = 1; i < cmdArgName.length; ++i) { + sbl.append(cmdArgName[i].substring(0, 1).toUpperCase()) + .append(cmdArgName[i].substring(1)); + } + String fieldName = sbl.toString(); + try { + Field field = CMDConf.class.getDeclaredField(fieldName); + if (field.getType().equals(String.class)) { + field.set(this, cmdArg[1]); + } else if (field.getType().equals(Integer.TYPE)) { + field.set(this, Integer.parseInt(cmdArg[1])); + } else { + field.set(this, true); + } + } catch (Exception e) { + LOGGER.warn("cmd arg " + fieldName + " invalid! " + e.getMessage()); + } + } + if (this.doipPort == -1) { + this.doipPort = this.servicePort + 2; + } + if (this.cmi.isEmpty() || !this.cmi.replaceAll("[^\\s]+", "").isEmpty()) { + this.cmi = String.valueOf(System.currentTimeMillis()); + this.overwrite = true; + LOGGER.info("create default cmi"); + } + return this; + } + + public void write(String path) { + try { + this.overwrite = false; + BufferedWriter bw = new BufferedWriter(new FileWriter(path)); + bw.write(new Gson().toJson(this)); + bw.flush(); + bw.close(); + LOGGER.info("write new configure"); + } catch (Exception e) { + LOGGER.warn("write failed!"); + } + } +} diff --git a/src/main/src/org/bdware/server/Entry.java b/src/main/src/org/bdware/server/Entry.java new file mode 100644 index 0000000..678234f --- /dev/null +++ b/src/main/src/org/bdware/server/Entry.java @@ -0,0 +1,99 @@ +package org.bdware.server; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + + +public class Entry { + //release 地址:47.93.86.250 root:i1235813 + public static void main(String[] args) { + try { + if (args == null || args.length < 2) { + printUsage(); + return; + } + switch (args[0]) { + case "CM": + case "ContractManager": + Thread t1 = new Thread(new Runnable() { + @Override + public void run() { + try { + // JavaContractServiceGrpcServer.init(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + t1.start(); + + Thread t2 = new Thread(new Runnable() { + @Override + public void run() { + String s = null; + try { + Thread.sleep(1000); + Process p = Runtime.getRuntime().exec("./bdledger_go"); + + BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); + BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); + + // read the output from the command + System.out.println("Here is the standard output of the command:\n"); + while ((s = stdInput.readLine()) != null) { + System.out.println(s); + } + + // read any errors from the attempted command + System.out.println("Here is the standard error of the command (if any):\n"); + while ((s = stdError.readLine()) != null) { + System.out.println(s); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + t2.start(); + //CMHttpServer.start(getPort(args)); + break; + case "NC": + case "NodeCenter": + //NodeCenterServer.start(getPort(args)); + break; + case "Index": +// IndexServer.start(getPort(args)); + default: + printUsage(); + } + } catch (Exception e) { + e.printStackTrace(); + printUsage(); + } + } + + private static void printUsage() { + System.out.println( + "Usage: java -jar bdserver.jar [Module] [Port]\n Example1: java -jar bdserver.jar CM 18000\n Example2: java -jar bdserver.jar NodeCenter 18001"); + + } + + private static int getPort(String[] args) { + if (args.length >= 2) + return Integer.parseInt(args[1]); + switch (args[0]) { + case "CM": + case "ContractManager": + return 18000; + case "NC": + case "NodeCenter": + return 18001; + case "Index": + return 1614; + default: + } + return -1; + } +} \ No newline at end of file diff --git a/src/main/src/org/bdware/server/action/Action.java b/src/main/src/org/bdware/server/action/Action.java new file mode 100644 index 0000000..e1c13fa --- /dev/null +++ b/src/main/src/org/bdware/server/action/Action.java @@ -0,0 +1,20 @@ +package org.bdware.server.action; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Action { + boolean httpAccess() default true; + + boolean websocketAccess() default true; + + boolean async() default false; + + long userPermission() default 0l; + + String[] alias() default {}; +} diff --git a/src/main/src/org/bdware/server/action/ActionExecutor.java b/src/main/src/org/bdware/server/action/ActionExecutor.java new file mode 100644 index 0000000..d078b6f --- /dev/null +++ b/src/main/src/org/bdware/server/action/ActionExecutor.java @@ -0,0 +1,173 @@ +package org.bdware.server.action; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.FileNotFoundException; +import java.io.RandomAccessFile; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +public class ActionExecutor { + private static final Logger LOGGER = LogManager.getLogger(ActionExecutor.class); + // ---------- use for profiling + static Map> allData = new ConcurrentHashMap<>(); + public ExecutorService executor; + // private Profiler profiler = new Profiler(); + public long permission; + Map staticData; + private Map> handlers; + + public ActionExecutor(ExecutorService executor, Object... classes) { + this.executor = executor; + permission = 0; + initHandlers(classes); + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + String caller = stackTraceElements[2].getClassName(); + caller += (int) (Math.random() * 10000); + staticData = new ConcurrentHashMap<>(); + allData.putIfAbsent(caller, staticData); + } + + public static Set getAECallerSet() { + return allData.keySet(); + } + + public static Map getStatistic(String caller) { + return allData.get(caller); + } + + public static Map> getAllData() { + return allData; + } + + @SuppressWarnings("unused") + public Map getStaticData() { + return staticData; + } + + // ---------- use for profiling + private void initHandlers(Object... objects) { + handlers = new HashMap<>(); + if (objects.length > 0) { + for (Object obj : objects) { + if (obj == null) continue; + Method[] methods = obj.getClass().getDeclaredMethods(); + for (Method method : methods) { + if (method.getAnnotation(Action.class) != null) { + if (method.getAnnotation(Action.class).alias().length == 0) { + handlers.put(method.getName(), new Pair<>(method, obj)); + if (!method.getReturnType().equals(Void.TYPE) + || method.getParameterCount() != 2) { + LOGGER.error( + "action ret is not void:" + + obj.getClass().getCanonicalName() + + "-->" + + method.getName()); + + System.exit(0); + } + } else { + for (String a : method.getAnnotation(Action.class).alias()) { + handlers.put(a, new Pair<>(method, obj)); + if (!method.getReturnType().equals(Void.TYPE) + || method.getParameterCount() != 2) { + LOGGER.error( + "action ret is not void:" + + obj.getClass().getCanonicalName() + + "-->" + + method.getName()); + + System.exit(0); + } + } + } + } + } + } + } + } + + public boolean checkPermission(Action a, final U args, long permission) { + return true; + } + + public Map> getHandlers() { + return handlers; + } + + public void handle(String action, final U args, final T callback) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + // logger.info("[ActionExecutor] handle : "+action); + + if (null != action) { + if (staticData.containsKey(action)) { + staticData.get(action).incrementAndGet(); + } else { + staticData.put(action, new AtomicInteger(1)); + } + } + // logger.debug("[ActionExecutor] handle : "); + if (!handlers.containsKey(action)) { + LOGGER.debug("unsupported action " + action); + throw new IllegalArgumentException("unsupported action " + action); + } + + final Pair pair = handlers.get(action); + Action actionAnnotations = pair.first.getAnnotation(Action.class); + if (!checkPermission(actionAnnotations, args, permission)) { + LOGGER.info("unauthorised action " + action); + throw new IllegalArgumentException("unauthorised action " + action); + } + + if (actionAnnotations.async()) { + executor.execute(() -> { + try { + pair.first.invoke(pair.second, args, callback); + } catch (Exception e) { + LOGGER.debug( + pair.first.getDeclaringClass().getCanonicalName() + + "->" + + pair.first.getName()); + e.printStackTrace(); + } + }); + } else { + pair.first.invoke(pair.second, args, callback); + } + } + + @SuppressWarnings("unused") + static class Profiler { + RandomAccessFile log; + + Profiler() { + try { + log = new RandomAccessFile("./log/profile.log", "rw"); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public static class Pair { + T first; + U second; + + public Pair(T f, U s) { + first = f; + second = s; + } + + public T first() { + return first; + } + } +} diff --git a/src/main/src/org/bdware/server/action/HttpResultCallback.java b/src/main/src/org/bdware/server/action/HttpResultCallback.java new file mode 100644 index 0000000..892ce51 --- /dev/null +++ b/src/main/src/org/bdware/server/action/HttpResultCallback.java @@ -0,0 +1,83 @@ +package org.bdware.server.action; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.HttpUtil; +import io.netty.handler.codec.http.HttpVersion; +import org.bdware.sc.conn.ByteUtil; +import org.bdware.sc.conn.ResultCallback; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; + +import static io.netty.handler.codec.http.HttpResponseStatus.OK; + +public class HttpResultCallback extends ResultCallback implements Runnable { + protected ChannelHandlerContext ctxField; + String jsonCallback; + Map extraHeaders = new HashMap<>(); + DefaultFullHttpResponse response; + byte[] bytes; + private boolean decodeAsB64 = false; + + public HttpResultCallback(ChannelHandlerContext ctx, String jsonCallback) { + ctxField = ctx; + this.jsonCallback = jsonCallback; + } + + @Override + public void onResult(String ret) { + if (jsonCallback != null) { + ret = (jsonCallback + "(" + ret + ")"); + } + if (ret != null && !ctxField.isRemoved()) { + bytes = null; + if (decodeAsB64) + try { + bytes = ByteUtil.decodeBASE64(ret); + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + bytes = bo.toByteArray(); + } + else { + bytes = ret.getBytes(); + } + assert bytes != null; + response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, Unpooled.wrappedBuffer(bytes)); + + for (String key : extraHeaders.keySet()) + response.headers().add(key, extraHeaders.get(key)); + ctxField.channel().eventLoop().execute(this); + } // Just ignore + + } + + public void addHeader(String key, String val) { + extraHeaders.put(key, val); + } + + @Override + public void run() { + HttpUtil.setContentLength(response, bytes.length); + ChannelFuture future = ctxField.writeAndFlush(response); + future.addListener(ChannelFutureListener.CLOSE); + + } + + public void setDecodeBase64() { + decodeAsB64 = true; + } +} +/* +scp ./libs/front-base-0.80.jar dev@023.node.internetapi.cn:./ +scp ./libs/front-base-0.80.jar dev@021.node.internetapi.cn:./ +scp ./libs/front-base-0.80.jar dev@024.node.internetapi.cn:./ + + +* */ \ No newline at end of file diff --git a/src/main/src/org/bdware/server/action/Result.java b/src/main/src/org/bdware/server/action/Result.java new file mode 100644 index 0000000..42edcd1 --- /dev/null +++ b/src/main/src/org/bdware/server/action/Result.java @@ -0,0 +1,16 @@ +package org.bdware.server.action; + +public class Result { + boolean status; + String msg; + String action = null; + Object data; + String responseID; + + Result() { + status = false; + msg = null; + data = ""; + responseID=""; + } +} \ No newline at end of file diff --git a/src/main/src/org/bdware/server/action/SyncResult.java b/src/main/src/org/bdware/server/action/SyncResult.java new file mode 100644 index 0000000..777ab23 --- /dev/null +++ b/src/main/src/org/bdware/server/action/SyncResult.java @@ -0,0 +1,126 @@ +package org.bdware.server.action; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.TimerTask; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.sc.ContractResult; +import org.bdware.sc.ContractResult.Status; +import org.bdware.sc.conn.InstrumentedResultCallback; +import org.bdware.sc.conn.ResultCallback; +import org.bdware.sc.util.JsonUtil; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class SyncResult { + public static final HashedWheelTimer timer = new HashedWheelTimer( + Executors.defaultThreadFactory(), + 5, + TimeUnit.MILLISECONDS, + 2); + private static final Logger LOGGER = LogManager.getLogger(SyncResult.class); + public Map waitObj = new ConcurrentHashMap<>(); + + public synchronized void wakeUp(String requestID, String result) { + ResultCallback ob = waitObj.get(requestID); + // TODO 难怪之前这是注释的。 + waitObj.remove(requestID); + // cancel timeout + if (ob != null) { + ob.cancelTimeOut(); + ob.onResult(result); + } + } + + public void instrumentWakeUp( + String requestID, + InstrumentedResultCallback instrumentedResultCallback, + JsonObject result) { + ResultCallback ob = waitObj.get(requestID); + // TODO 难怪之前这是注释的。 + waitObj.remove(requestID); + // cancel timeout + if (ob != null) { + ob.cancelTimeOut(); + instrumentedResultCallback.onResult(ob, result); + } + } + + public void sleep(String requestID, ResultCallback cb) { + // TODO 这里有bug + sleepWithTimeout(requestID, cb, 20); + } + + public void sleepWithTimeout(final String requestID, ResultCallback cb, int timeOut) { + if (!waitObj.containsKey(requestID)) { + CancelTask tt = new CancelTask(requestID); + Timeout timeout = timer.newTimeout(tt, timeOut, TimeUnit.SECONDS); + // logger.debug("reqID:" + requestID + " createTimeout:" + timeout); + cb.setTimeOut(timeout); + waitObj.put(requestID, cb); + } else { + LOGGER.debug("[Duplicated RequestID]" + requestID); + } + } + + public ContractResult syncSleep(String requestID) { + ContractResultCallback cb = new ContractResultCallback(); + sleep(requestID, cb); + + synchronized (cb) { + try { + cb.wait(20000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return cb.cr; + } + + public boolean canIssue() { + // TODO add flow control + int waitSize = waitObj.keySet().size(); + + return true; + } + + public static class ContractResultCallback extends ResultCallback { + ContractResult cr = new ContractResult(Status.Error, new JsonPrimitive("Timeout!!")); + int reRoute = 0; + + @Override + public void onResult(String str) { + cr = JsonUtil.fromJson(str, ContractResult.class); + synchronized (this) { + this.notifyAll(); + } + } + + public int getReRouteCount() { + return reRoute; + } + + public void incReRouteCount() { + reRoute++; + } + } + + class CancelTask implements TimerTask { + String requestID; + + CancelTask(String requestID) { + this.requestID = requestID; + } + + public void run(Timeout timeout) { + ContractResult cr = new ContractResult(Status.Error, new JsonPrimitive("Timeout!")); + wakeUp(requestID, JsonUtil.toJson(cr)); + } + } +} diff --git a/src/main/src/org/bdware/server/http/FileDownloaderCallback.java b/src/main/src/org/bdware/server/http/FileDownloaderCallback.java new file mode 100644 index 0000000..315648c --- /dev/null +++ b/src/main/src/org/bdware/server/http/FileDownloaderCallback.java @@ -0,0 +1,61 @@ +package org.bdware.server.http; + +import io.netty.buffer.Unpooled; +import io.netty.channel.*; +import io.netty.handler.codec.http.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.server.action.HttpResultCallback; + +import java.io.File; +import java.io.RandomAccessFile; + +import static io.netty.handler.codec.http.HttpResponseStatus.OK; + +public class FileDownloaderCallback extends HttpResultCallback { + private static final Logger LOGGER = LogManager.getLogger(FileDownloaderCallback.class); + HttpRequest req; + + public FileDownloaderCallback(ChannelHandlerContext ctx, HttpRequest req) { + super(ctx, null); + this.req = req; + } + + public void onResult(final String filePath) { + try { + final RandomAccessFile file = new RandomAccessFile(filePath, "r"); + HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + // 设置文件格式内容 + response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/x-msdownload"); + response.headers().set(HttpHeaderNames.CONTENT_DISPOSITION, + "attachment;filename=" + new File(filePath).getName()); + HttpUtil.setKeepAlive(response, HttpUtil.isKeepAlive(req)); + HttpUtil.setContentLength(response, file.length()); + LOGGER.debug("FileLength:" + file.length()); + ctxField.write(response); + ChannelFuture future = ctxField.write(new DefaultFileRegion(file.getChannel(), 0, file.length()), + ctxField.newProgressivePromise()); + ctxField.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); + future.addListener(new ChannelProgressiveFutureListener() { + @Override + public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) { + } + + @Override + public void operationComplete(ChannelProgressiveFuture future) throws Exception { + file.close(); + LOGGER.debug("delete file " + filePath + ": " + new File(filePath).delete()); + } + }); + if (!HttpUtil.isKeepAlive(req)) + future.addListener(ChannelFutureListener.CLOSE); + ctxField.flush(); + } catch (Exception e) { + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, + Unpooled.wrappedBuffer("File Not Found".getBytes())); + ChannelFuture f = ctxField.writeAndFlush(response); + f.addListener(ChannelFutureListener.CLOSE); + ctxField.close(); + } + } +} diff --git a/src/main/src/org/bdware/server/http/HttpFileHandleAdapter.java b/src/main/src/org/bdware/server/http/HttpFileHandleAdapter.java new file mode 100644 index 0000000..2bb6236 --- /dev/null +++ b/src/main/src/org/bdware/server/http/HttpFileHandleAdapter.java @@ -0,0 +1,157 @@ +package org.bdware.server.http; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.handler.stream.ChunkedFile; + +import java.io.File; +import java.io.FileFilter; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.regex.Pattern; + +import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; + +public class HttpFileHandleAdapter extends SimpleChannelInboundHandler { + private static final Pattern ALLOWED_FILE_NAME = + Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*"); + private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*"); + FileFilter fileFilter; + private String location; + + public HttpFileHandleAdapter(String path, FileFilter fileFilter) { + location = path; + this.fileFilter = fileFilter; + } + + public static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) { + FullHttpResponse response = + new DefaultFullHttpResponse( + HTTP_1_1, + status, + Unpooled.wrappedBuffer( + ("Failure: " + status.toString() + "\r\n").getBytes())); + response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8"); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + } + + public static void appendContentType(String path, HttpHeaders headers) { + if (path.endsWith(".html")) { + headers.set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8"); + } else if (path.endsWith(".js")) { + headers.set(HttpHeaderNames.CONTENT_TYPE, "application/x-javascript; charset=utf-8"); + } else if (path.endsWith(".css")) { + headers.set(HttpHeaderNames.CONTENT_TYPE, "text/css; charset=UTF-8"); + } else if (path.endsWith(".ico")) { + headers.set(HttpHeaderNames.CONTENT_TYPE, "image/x-icon;"); + } else if (path.endsWith(".svg")) { + headers.set(HttpHeaderNames.CONTENT_TYPE, "text/xml;charset=utf-8"); + } + } + + private static void send100Continue(ChannelHandlerContext ctx) { + FullHttpResponse response = + new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE); + ctx.writeAndFlush(response); + } + + private String sanitizeUri(String uri) { + try { + // 使用JDK的URLDecoder进行解码 + uri = URLDecoder.decode(uri, "UTF-8"); + } catch (UnsupportedEncodingException e) { + try { + uri = URLDecoder.decode(uri, "ISO-8859-1"); + } catch (UnsupportedEncodingException e1) { + throw new Error(); + } + } + + if (!uri.startsWith("/")) { + return null; + } + if (uri.contains("..")) { + return null; + } + // 将硬编码的文件路径 + uri = uri.replace('/', File.separatorChar); + if (uri.contains(File.separator + '.') + || uri.contains('.' + File.separator) + || uri.startsWith(".") + || uri.endsWith(".") + || INSECURE_URI.matcher(uri).matches()) { + return null; + } + return System.getProperty("user.dir") + File.separator + uri; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) + throws Exception { + // 获取URI + request.retain(); + // System.out.println("[HttpFileHandlerAdapter]request.uri:" + request.uri()); + // String[] hoString = request.duplicate().toString().split("\n"); + // if (request.uri().equals("/favicon.ico")) { + // request.setUri("/SCIDE/favicon.ico"); + // } + String uri = request.uri(); + + if (uri.contains("..")) { + sendError(ctx, HttpResponseStatus.BAD_REQUEST); + return; + } + + uri = uri.replaceFirst("/SCIDE", ""); + uri = uri.replaceFirst("\\?.*$", ""); + if (uri.equals("/") || uri.equals("./") || uri.length() == 0) { + uri = "/index.html"; + } + boolean isTrue = isFile(uri); + // 根据路径地址构建文件 + if (isTrue) { + String path = location + uri; + File html = new File(path); + // 状态为1xx的话,继续请求 + if (HttpUtil.is100ContinueExpected(request)) { + send100Continue(ctx); + } + // 当文件不存在的时候,将资源指向NOT_FOUND + if (!html.exists() || html.isDirectory()) { + sendError(ctx, HttpResponseStatus.NOT_FOUND); + return; + } + final RandomAccessFile file = new RandomAccessFile(html, "r"); + HttpResponse response = + new DefaultHttpResponse(request.protocolVersion(), HttpResponseStatus.OK); + // 设置文件格式内容 + appendContentType(path, response.headers()); + boolean keepAlive = HttpUtil.isKeepAlive(request); + HttpUtil.setContentLength(response, file.length()); + if (keepAlive) { + HttpUtil.setKeepAlive(response, true); + } + ctx.write(response); + // 同过netty的村可多File对象直接将文件写入到发送缓冲区,最后为sendFileFeature增加GenericFeatureListener, + // 如果发送完成,打印“Transfer complete” + ctx.write(new ChunkedFile(file, 0, file.length(), 512 * 1024), ctx.newPromise()); + // 写入文件尾部 + ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); + if (!keepAlive) { + future.addListener(ChannelFutureListener.CLOSE); + } + future.addListener(arg0 -> file.close()); + } else { + sendError(ctx, HttpResponseStatus.NOT_FOUND); + } + } + + private boolean isFile(String path) { + return fileFilter.accept(new File(path)); + } +} diff --git a/src/main/src/org/bdware/server/http/HttpMethod.java b/src/main/src/org/bdware/server/http/HttpMethod.java new file mode 100644 index 0000000..d33ca10 --- /dev/null +++ b/src/main/src/org/bdware/server/http/HttpMethod.java @@ -0,0 +1,36 @@ +package org.bdware.server.http; + +public enum HttpMethod { + OPTIONS, + GET, + HEAD, + POST, + PUT, + PATCH, + DELETE, + TRACE, + CONNECT; + + io.netty.handler.codec.http.HttpMethod get() { + switch (this) { + case OPTIONS: + return io.netty.handler.codec.http.HttpMethod.OPTIONS; + case HEAD: + return io.netty.handler.codec.http.HttpMethod.HEAD; + case POST: + return io.netty.handler.codec.http.HttpMethod.POST; + case PUT: + return io.netty.handler.codec.http.HttpMethod.PUT; + case PATCH: + return io.netty.handler.codec.http.HttpMethod.PATCH; + case DELETE: + return io.netty.handler.codec.http.HttpMethod.DELETE; + case TRACE: + return io.netty.handler.codec.http.HttpMethod.TRACE; + case CONNECT: + return io.netty.handler.codec.http.HttpMethod.CONNECT; + default: + return io.netty.handler.codec.http.HttpMethod.GET; + } + } +} diff --git a/src/main/src/org/bdware/server/http/URIHandler.java b/src/main/src/org/bdware/server/http/URIHandler.java new file mode 100644 index 0000000..57f1412 --- /dev/null +++ b/src/main/src/org/bdware/server/http/URIHandler.java @@ -0,0 +1,113 @@ +package org.bdware.server.http; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; + +public class URIHandler { + private static final Logger LOGGER = LogManager.getLogger(URIHandler.class); + Map>> handlers; + + public URIHandler() { + handlers = new HashMap<>(); + } + + public void register(Object obj) { + register(obj.getClass(), obj); + } + + public void register(Class clz) { + register(clz, null); + } + + public void register(Class clz, Object obj) { + for (Method m : clz.getDeclaredMethods()) { + URIPath path = m.getAnnotation(URIPath.class); + if (path != null) { + HttpMethod method = path.method(); + List> handlerList = getOrCreate(method); + for (String str : path.value()) { + m.setAccessible(true); + handlerList.add(new Tuple<>(str, m, obj)); + } + } + } + for (List> handlerList : handlers.values()) { + sortHandlerList(handlerList); + } + } + + protected List> getOrCreate(HttpMethod method) { + return handlers.computeIfAbsent(method.get(), k -> new ArrayList<>()); + } + + private void sortHandlerList(List> handlerList) { + handlerList.sort((o1, o2) -> { + int delta = o2.t.length() - o1.t.length(); + return delta == 0 ? o1.t.compareTo(o2.t) : delta; + }); + } + + public void handle(ChannelHandlerContext ctx, FullHttpRequest msg) { + try { + List> handlerList = handlers.get(msg.method()); + for (Tuple t : handlerList) + if (msg.uri().startsWith(t.t)) { + t.u.invoke(t.s, ctx, msg); + return; + } + sendUnsupported(ctx); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void printURIHandlers() { + StringBuilder sbl = new StringBuilder("URIHandlers:\n"); + for (io.netty.handler.codec.http.HttpMethod m : handlers.keySet()) { + sbl.append("\t").append(m.name()).append("\n"); + for (Tuple t : handlers.get(m)) { + String className = t.u.getDeclaringClass().getSimpleName(); + sbl.append("\t\t").append(t.t.isEmpty() ? "" : t.t).append(" --> ") + .append(className.isEmpty() ? "null" : className) + .append(".").append(t.u.getName()).append("\n"); + } + } + LOGGER.info(sbl.substring(0, sbl.length() - 1)); + } + + private void sendUnsupported(ChannelHandlerContext ctx) { + FullHttpResponse response = + new DefaultFullHttpResponse( + HTTP_1_1, + HttpResponseStatus.BAD_REQUEST, + Unpooled.wrappedBuffer( + ("Failure: " + HttpResponseStatus.BAD_REQUEST + "\r\n") + .getBytes())); + response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8"); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + } + + static class Tuple { + T t; + U u; + S s; + + Tuple(T t, U u, S s) { + this.t = t; + this.u = u; + this.s = s; + } + } +} diff --git a/src/main/src/org/bdware/server/http/URIPath.java b/src/main/src/org/bdware/server/http/URIPath.java new file mode 100644 index 0000000..c760cf7 --- /dev/null +++ b/src/main/src/org/bdware/server/http/URIPath.java @@ -0,0 +1,13 @@ +package org.bdware.server.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface URIPath { + String[] value() default {""}; + HttpMethod method() default HttpMethod.GET; +} diff --git a/src/main/src/org/bdware/server/nodecenter/Response.java b/src/main/src/org/bdware/server/nodecenter/Response.java new file mode 100644 index 0000000..701bc06 --- /dev/null +++ b/src/main/src/org/bdware/server/nodecenter/Response.java @@ -0,0 +1,9 @@ +package org.bdware.server.nodecenter; + +public class Response { + String responseID; + public String action; + public Object data; + public long executeTime; + public boolean isPrivate; +} diff --git a/src/main/src/org/bdware/server/nodecenter/ResultBack.java b/src/main/src/org/bdware/server/nodecenter/ResultBack.java new file mode 100644 index 0000000..2a57cf9 --- /dev/null +++ b/src/main/src/org/bdware/server/nodecenter/ResultBack.java @@ -0,0 +1,14 @@ +package org.bdware.server.nodecenter; + +public class ResultBack { + public boolean status; + public String msg; + public String action = null; + public Object data; + + public ResultBack() { + status = false; + msg = null; + data = ""; + } +} \ No newline at end of file diff --git a/src/main/src/org/bdware/server/nodecenter/UserMySQL.java b/src/main/src/org/bdware/server/nodecenter/UserMySQL.java new file mode 100644 index 0000000..dad17d1 --- /dev/null +++ b/src/main/src/org/bdware/server/nodecenter/UserMySQL.java @@ -0,0 +1,5 @@ +package org.bdware.server.nodecenter; + +public class UserMySQL { + +} diff --git a/src/main/src/org/bdware/server/nodecenter/client/CMNodeBean.java b/src/main/src/org/bdware/server/nodecenter/client/CMNodeBean.java new file mode 100644 index 0000000..4f8573d --- /dev/null +++ b/src/main/src/org/bdware/server/nodecenter/client/CMNodeBean.java @@ -0,0 +1,85 @@ +package org.bdware.server.nodecenter.client; + +import com.google.gson.reflect.TypeToken; +import org.bdware.sc.bean.ContractDesp; +import org.bdware.sc.util.JsonUtil; + +import java.util.List; +import java.util.Map; + +public class CMNodeBean { + public List contracts; + public String pubKey; + public String nodeName; + public String udpID; + public String ipPort; + public String cimanager = ""; + + public CMNodeBean(String publicKeyStr) { + pubKey = publicKeyStr; + } + + // TODO nodeMangerPubkey + public void updateContract(Map json) { + String jsonStr = json.get("contracts"); + contracts = JsonUtil.fromJson(jsonStr, new TypeToken>() { + }.getType()); +// KeyValueDBUtil.instance.setValue(NCTables.NodesDB.toString(), pubKey, JsonUtil.toJson(this)); + + } + + // when the center received an event, publish it to subscriber. + + public String formatContractName(String contractIDOrName) { + if (null != contracts) { + for (ContractDesp desp : contracts) { + if (desp.contractID.equals(contractIDOrName) || desp.contractName.equals(contractIDOrName)) { + return desp.contractName; + } + } + } + return null; + } + + public boolean containsContract(String contractIDOrName) { + if (null != contracts) { + for (ContractDesp desp : contracts) { + if (desp.contractID.equals(contractIDOrName) || desp.contractName.equals(contractIDOrName)) + return true; + } + } + return false; + } + + public boolean containsEvent(String contractIDOrName, String event) { + if (null != contracts) { + for (ContractDesp desp : contracts) { + if (desp.contractID.equals(contractIDOrName) || desp.contractName.equals(contractIDOrName)) { + if (desp.events.containsKey(event)) + return true; + } + } + } + return false; + } + + public void removeCIManager(String string) { + System.out.println("removeCIManager" + string); + int start = this.cimanager.indexOf(string); + if (start > 0) { + this.cimanager = this.cimanager.substring(0, start) + .concat(this.cimanager.substring(start + 130)); + } + } + + public void addCIManager(String string) { + System.out.println("addCIManager" + string); + this.cimanager = this.cimanager.concat(" " + string); + } + + public void setCIManager(String string) { + this.cimanager = string; + + } + +} \ No newline at end of file diff --git a/src/main/src/org/bdware/server/permission/Permission.java b/src/main/src/org/bdware/server/permission/Permission.java new file mode 100644 index 0000000..aebb447 --- /dev/null +++ b/src/main/src/org/bdware/server/permission/Permission.java @@ -0,0 +1,93 @@ +package org.bdware.server.permission; + +public enum Permission { +// GetSessionID(0), GetRole(0), Login(0), // 默认权限设置为0 +// ApplyRole(1 << 0), // 匿名用户申请成为节点管理员(NodePortal)角色 +// NodeStateList(1 << 1), // 中心节点查看节点管理员的所管理所有节点的状态 +// AuthNodeManager(1 << 2), // 授权节点管理员 +// DeleteNodeManager(1 << 3), // 从网络中删除某个节点管理员 +// ListAllUsers(1 << 4), // ListAllUser +// ListApplyUser(1 << 5), // ListApplyUser +// ListTrustCluster(1 << 6), // 查看可信执行集群列表 +// AssignTrustedCluster(1 << 7), // 分配可信执行集群 +// +// // ==================NodePotral=============== +// //ApplyNodeRole(1<<6),//申请节点角色 +// AuthNodeRole(1 << 8), // 授权角色 +// DeleteRole(1 << 9), // 从用户角色中删除某一种角色 +// ListAllAuthUsers(1 << 10), // 查看已授权用户 +// ListUnAuthUsers(1 << 11), // 查看未授权用户 +// +// StartContract(1 << 12), ExecuteContract(1 << 13), StopContract(1 << 14), // stop和kill一样 +// UploadContract(1 << 15), // 上传合约代码(修改代码、更新合约代码、保存代码) +// DownloadContract(1 << 16), // 下载合约代码 +// DeleteContract(1 << 17), // 删除合约代码 +// +// ContractCodeStatisticsList(1 << 18), // 查看合约代码统计数据(合约文件大小) +// StaticAnalysis(1 << 19), // 静态分析 +// ConfigureContractPermission(1 << 20), // 配置合约权限 +// ContractProgressList(1L << 22L), // 查看合约进程(listContractProcess) +// +// QueryActionLog(1L << 24L), // 增加listLog(时间戳) +// QueryUserStateLog(1L << 25L), // 查看节点日志 +// ListLocalNodeStatus(1L << 26L), // 节点状态(此节点) +// ListContractLog(1L << 27L), // 合约日志 +// +// TimeTravel(1L << 28L), ManualDump(1L << 29L), // 手动dump +// ForkContractStatus(1L << 30L), // 合约状态从别处迁移到自己本地 +// ConfigureNode(1L << 31L), // 配置节点信息 +// listProjects(1L << 32L),// 合约提供者 + + + // 新加的一些权限 + // listLicence(1L<<33L)//证书列表 updateLicence权限也写成这个了,有没有必要分开 + + // TODO: 20205/20 需要整理权限就权限和最新的权限 + + // CenterManager (其他部分代码中出现的,暂未合并整理) + ApplyRole(1 << 0), + NodeStateList(1 << 1), + AuthNodeManager(1 << 2), + ListAllUsers(1 << 3), + ListApplyUser(1 << 4), + DeleteNodeManager(1 << 5), + ListTrustCluster(1 << 6), + AssignTrustedCluster(1 << 7), + QueryActionLog(1 << 8), + QueryUserStateLog(1 << 9), + + // Node + ConfigureNode(1 << 10), // 其他地方代码中的权限 + ManageNode(1 << 10), // 节点管理 + GetNodeInfo(1 << 11), // 节点信息获取 + + ContractCodeStatisticsList(1 << 12), // 其他地方代码中的权限 + ConfigureContractPermission(1 << 13), // 其他地方代码中的权限 + EditContract(1 << 14), // 编辑合约 + ListProject(1L << 15), // 查看project信息 + StaticAnalysis(1L << 16), // 静态分析 + Compile(1L << 17), // 编译相关及其他权限类似操作 + + ContractPermissionList(1L << 18), // 查看合约权限 + ListContractProgress(1L << 19), // 合约进程列表 + CheckContractStatus(1L << 20), // 查看合约状态(被调用多少次,占用内存等等) + TimeTravel(1L << 21), // 其他地方代码中的权限 + ListContractLog(1L << 22), // 查看合约日志 + ManageMemory(1L << 23), // 内存管理 + CreateLedger(1L << 24), // ledger相关 + + ManualDump(1L << 25), // 手动dump + ManageContract(1L << 26), // 更改合约运行状态 + + TakeScreenShot(1L << 27); + + public final long value; + + Permission(long value) { + this.value = value; + } + + public long getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/src/org/bdware/server/permission/Role.java b/src/main/src/org/bdware/server/permission/Role.java new file mode 100644 index 0000000..379a962 --- /dev/null +++ b/src/main/src/org/bdware/server/permission/Role.java @@ -0,0 +1,43 @@ +package org.bdware.server.permission; + +public enum Role { + CenterManager(0x3ffL), + NodeManager(0xe41L), + Node(0x1L), + ContractProvider(0x3f000L), + ContractInstanceManager(0x7ff10c0L), + ContractUser(0x5c0000L), + Anonymous(0); + + long value; + + Role(long v) { + value = v; + }; + + public static Role parse(String str) { + try { + return valueOf(str); + } catch (Exception e) { + return Anonymous; + } + } + + public long getValue() { + return value; + } + + public static long compoundValue(String[] roles) { + long ret = 0; + if (roles != null) { + for (String role : roles) { + ret |= parse(role).value; + } + } + return ret; + } + + public String getString(Role role) { + return role.toString(); + } +} diff --git a/src/main/src/org/bdware/server/ws/DelimiterBasedFrameEncoder.java b/src/main/src/org/bdware/server/ws/DelimiterBasedFrameEncoder.java new file mode 100644 index 0000000..50c8950 --- /dev/null +++ b/src/main/src/org/bdware/server/ws/DelimiterBasedFrameEncoder.java @@ -0,0 +1,17 @@ +package org.bdware.server.ws; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +public class DelimiterBasedFrameEncoder extends MessageToByteEncoder { + static byte[] delimiter = "wonbifoodie".getBytes(); + + @Override + protected void encode(ChannelHandlerContext arg0, ByteBuf in, ByteBuf out) throws Exception { + // System.out.println("[DelimiterBasedFrameEncoder] write:" + + // in.readableBytes()); + out.writeBytes(in); + out.writeBytes(delimiter); + } +} diff --git a/src/main/src/org/bdware/server/ws/DelimiterCodec.java b/src/main/src/org/bdware/server/ws/DelimiterCodec.java new file mode 100644 index 0000000..1b00601 --- /dev/null +++ b/src/main/src/org/bdware/server/ws/DelimiterCodec.java @@ -0,0 +1,17 @@ +package org.bdware.server.ws; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.CombinedChannelDuplexHandler; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; + +public class DelimiterCodec + extends CombinedChannelDuplexHandler< + DelimiterBasedFrameDecoder, DelimiterBasedFrameEncoder> { + public DelimiterCodec() { + ByteBuf buf = Unpooled.wrappedBuffer(DelimiterBasedFrameEncoder.delimiter); + init( + new DelimiterBasedFrameDecoder(10 * 1024 * 1024, buf), + new DelimiterBasedFrameEncoder()); + } +} diff --git a/src/main/src/org/bdware/server/ws/WebSocketIndexPageHandler.java b/src/main/src/org/bdware/server/ws/WebSocketIndexPageHandler.java new file mode 100644 index 0000000..ef299e3 --- /dev/null +++ b/src/main/src/org/bdware/server/ws/WebSocketIndexPageHandler.java @@ -0,0 +1,100 @@ +package org.bdware.server.ws; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpUtil; +import io.netty.handler.ssl.SslHandler; + +import static io.netty.handler.codec.http.HttpHeaderNames.*; +import static io.netty.handler.codec.http.HttpMethod.*; +import static io.netty.handler.codec.http.HttpResponseStatus.*; + +/** + * Outputs index page content. + */ +public class WebSocketIndexPageHandler extends SimpleChannelInboundHandler { + + private final String websocketPath; + + public WebSocketIndexPageHandler(String websocketPath) { + this.websocketPath = websocketPath; + } + + @SuppressWarnings("deprecation") + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { + // Handle a bad request. + if (!req.getUri().startsWith("/SCIDE/SCExecutor")) { + sendHttpResponse(ctx, req, + new DefaultFullHttpResponse(req.protocolVersion(), NOT_FOUND, ctx.alloc().buffer(0))); + return; + } + if (!req.decoderResult().isSuccess()) { + sendHttpResponse(ctx, req, + new DefaultFullHttpResponse(req.protocolVersion(), BAD_REQUEST, ctx.alloc().buffer(0))); + return; + } + + // Allow only GET methods. + if (!GET.equals(req.method())) { + sendHttpResponse(ctx, req, + new DefaultFullHttpResponse(req.protocolVersion(), FORBIDDEN, ctx.alloc().buffer(0))); + return; + } + + // Send the index page + if ("/SCIDE/SCExecutor/".equals(req.uri()) || "/SCIDE/SCExecutor/index.html".equals(req.uri())) { + String webSocketLocation = getWebSocketLocation(ctx.pipeline(), req, websocketPath); + ByteBuf content = WebSocketServerIndexPage.getContent(webSocketLocation); + FullHttpResponse res = new DefaultFullHttpResponse(req.protocolVersion(), OK, content); + res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); + HttpUtil.setContentLength(res, content.readableBytes()); + sendHttpResponse(ctx, req, res); + } else { + sendHttpResponse(ctx, req, + new DefaultFullHttpResponse(req.protocolVersion(), NOT_FOUND, ctx.alloc().buffer(0))); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } + + private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) { + // Generate an error page if response getStatus code is not OK (200). + HttpResponseStatus responseStatus = res.status(); + if (responseStatus.code() != 200) { + ByteBufUtil.writeUtf8(res.content(), responseStatus.toString()); + HttpUtil.setContentLength(res, res.content().readableBytes()); + } + // Send the response and close the connection if necessary. + boolean keepAlive = HttpUtil.isKeepAlive(req) && responseStatus.code() == 200; + HttpUtil.setKeepAlive(res, keepAlive); + ChannelFuture future = ctx.writeAndFlush(res); + if (!keepAlive) { + future.addListener(ChannelFutureListener.CLOSE); + } + } + + private static String getWebSocketLocation(ChannelPipeline cp, HttpRequest req, String path) { + String protocol = "ws"; + if (cp.get(SslHandler.class) != null) { + // SSL in use so use Secure WebSockets + protocol = "wss"; + } + return protocol + "://" + req.headers().get(HttpHeaderNames.HOST) + path; + } +} \ No newline at end of file diff --git a/src/main/src/org/bdware/server/ws/WebSocketServerIndexPage.java b/src/main/src/org/bdware/server/ws/WebSocketServerIndexPage.java new file mode 100644 index 0000000..c5faabd --- /dev/null +++ b/src/main/src/org/bdware/server/ws/WebSocketServerIndexPage.java @@ -0,0 +1,105 @@ +package org.bdware.server.ws; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +/** Generates the demo HTML page which is served at http://localhost:8080/ */ +public final class WebSocketServerIndexPage { + + private static final String NEWLINE = "\r\n"; + + public static ByteBuf getContent(String webSocketLocation) { + String str = + "Web Socket Test" + + NEWLINE + + "" + + NEWLINE + + "" + + NEWLINE + + "
" + + NEWLINE + + "" + + "" + + NEWLINE + + "

Output

" + + NEWLINE + + "" + + NEWLINE + + "
" + + NEWLINE + + "" + + NEWLINE + + "" + + NEWLINE; + return Unpooled.wrappedBuffer(str.getBytes()); + } + + private WebSocketServerIndexPage() { + // Unused + } +} diff --git a/src/main/src/resources/log4j.properties b/src/main/src/resources/log4j.properties new file mode 100644 index 0000000..0ab7b03 --- /dev/null +++ b/src/main/src/resources/log4j.properties @@ -0,0 +1,8 @@ +### 设置### +log4j.rootLogger = debug,stdout + +### 输出信息到控制抬 ### +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target = System.out +log4j.appender.stdout.layout = org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{HH:mm:ss.SSS} %m (%F:%L)%n \ No newline at end of file diff --git a/src/main/thirdparty/org/bdware/server/IndexServer.java b/src/main/thirdparty/org/bdware/server/IndexServer.java new file mode 100644 index 0000000..839f84c --- /dev/null +++ b/src/main/thirdparty/org/bdware/server/IndexServer.java @@ -0,0 +1,60 @@ +package org.bdware.server; + + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.stream.ChunkedWriteHandler; +import org.bdware.server.http.IndexHttpHandler; + +public class IndexServer { + final String PATH = "/Index"; + private final int port; + + private IndexServer(int port) { + this.port = port; + } + + public static void main(String[] args) throws Exception { +// NodeCenterServer.start(18001); + start(1614); + + } + + public static void start(int port) throws Exception { + System.out.println("[IndexServer] start at:" + port); + new IndexServer(port).start(); + } + + private void start() throws Exception { + + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + try { + + final IndexHttpHandler serverHandler = new IndexHttpHandler(); + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).localAddress(port) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel arg0) throws Exception { + arg0.pipeline().addLast(new HttpServerCodec()).addLast(new HttpObjectAggregator(65536)) + .addLast(new ChunkedWriteHandler()).addLast(serverHandler); + } + }); + Channel ch = b.bind(port).sync().channel(); + ch.closeFuture().sync(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } +} diff --git a/src/main/thirdparty/org/bdware/server/action/IndexAction.java b/src/main/thirdparty/org/bdware/server/action/IndexAction.java new file mode 100644 index 0000000..45b4cf6 --- /dev/null +++ b/src/main/thirdparty/org/bdware/server/action/IndexAction.java @@ -0,0 +1,230 @@ +package org.bdware.server.action; + +import com.google.gson.JsonObject; +import org.bdware.sc.conn.ResultCallback; +import org.bdware.sc.index.LenVarTimeSerialIndex2; +import org.bdware.sc.util.HashUtil; +import org.bdware.sc.util.JsonUtil; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class IndexAction { + + static final String MISSING_ARGUMENT = "{\"status\":\"Errorr\",\"data\":\"missing arguments\"}"; + static Map fileMap = new HashMap<>(); + + public IndexAction() { + } + + @Action(async = true) + public void createFile(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("dataLength")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + try { + String fileName = "./" + args.get("file").getAsString(); + File f = new File(fileName + ".datasize"); + FileOutputStream fout = new FileOutputStream(f); + int dataLength = args.get("dataLength").getAsInt(); + for (int i = 0; i < dataLength; i++) + fout.write(1); + fout.close(); +// LenVarTimeSerialIndex2 index = getIndexFile(fileName); + resultCallback.onResult( + "{\"status\":\"Success\",\"dataLength\":" + dataLength + ",\".datasize\":" + f.length() + "}"); + + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + @Action(async = true) + public void index(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("content")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + + try { + LenVarTimeSerialIndex2 index = getIndexFile(args.get("file").getAsString()); + String content = args.get("content").getAsString(); + long ret = index.index(HashUtil.str16ToBytes(content)); + resultCallback.onResult("{\"status\":\"Success\",\"date\":" + ret + "}"); + + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + @Action(async = true) + public void dataSize(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + try { + LenVarTimeSerialIndex2 index = getIndexFile(args.get("file").getAsString()); + + resultCallback.onResult("{\"dataSize\":" + index.dataSize + ",\"fileSize\":" + index.fileSize + "}"); + + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + @Action(async = true) + public void requestByTime(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("startTime")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("endTime")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + try { + LenVarTimeSerialIndex2 index = getIndexFile(args.get("file").getAsString()); + long startTime = args.get("startTime").getAsLong(); + long endTime = args.get("endTime").getAsLong(); + List result = index.requestByTime(startTime, endTime); + returnSuccess(resultCallback, result); + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + private void returnSuccess(ResultCallback resultCallback, List result) { + Response r = new Response(); + r.status = "Success"; + r.list = new ArrayList<>(); + for (byte[] bytes : result) { + r.list.add(new Data(bytes)); + } + resultCallback.onResult(JsonUtil.toJson(r)); + } + + @Action(async = true) + public void request(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("offset")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("count")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + try { + LenVarTimeSerialIndex2 index = getIndexFile(args.get("file").getAsString()); + long offset = args.get("offset").getAsLong(); + int count = args.get("count").getAsInt(); + List result = index.request(offset, count); + + returnSuccess(resultCallback, result); + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + @Action(async = true) + public void getSize(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + try { + LenVarTimeSerialIndex2 index = getIndexFile(args.get("file").getAsString()); + int size = (int) index.size(); + resultCallback.onResult("{\"status\":\"Success\",\"size\":" + size + "}"); + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + private LenVarTimeSerialIndex2 getIndexFile(String str) { + LenVarTimeSerialIndex2 indexFile = fileMap.get(str); + if (indexFile == null) { + indexFile = new LenVarTimeSerialIndex2(str); + fileMap.put(str, indexFile); + } + return indexFile; + } + + @Action(async = true) + public void manullyIndex(JsonObject args, final ResultCallback resultCallback) { + if (!args.has("date")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("content")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + if (!args.has("file")) { + resultCallback.onResult(MISSING_ARGUMENT); + return; + } + try { + LenVarTimeSerialIndex2 index = getIndexFile(args.get("file").getAsString()); + long date = Long.parseLong(args.get("date").getAsString()); + String content = args.get("content").getAsString(); + index.manullyIndex(date, HashUtil.str16ToBytes(content)); + resultCallback.onResult("{\"status\":\"Success\"}"); + + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + resultCallback.onResult(bo.toString()); + } + } + + static class Response { + String status; + List list; + } + + static class Data { + long date; + String data; + + public Data(byte[] bytes) { + date = HashUtil.bytes2Long(bytes); + data = HashUtil.byteArray2Str(bytes, 8); + } + } +} diff --git a/src/main/thirdparty/org/bdware/server/http/IndexHttpHandler.java b/src/main/thirdparty/org/bdware/server/http/IndexHttpHandler.java new file mode 100644 index 0000000..f433a7d --- /dev/null +++ b/src/main/thirdparty/org/bdware/server/http/IndexHttpHandler.java @@ -0,0 +1,157 @@ +package org.bdware.server.http; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.sc.conn.ResultCallback; +import org.bdware.sc.util.JsonUtil; +import org.bdware.server.action.ActionExecutor; +import org.bdware.server.action.HttpResultCallback; +import org.bdware.server.action.IndexAction; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; + +import static io.netty.handler.codec.http.HttpResponseStatus.OK; + +@Sharable +public class IndexHttpHandler extends SimpleChannelInboundHandler { + private static final String PARAM_ACTION = "action"; + private static final String UNSUPPORTED_HTTP_METHOD = "{\"msg\":\"unsupported http method\"}"; + private static final String UNSUPPORTED_ACTION = "{\"msg\":\"unsupported action\"}"; + private static final Logger LOGGER = LogManager.getLogger(IndexHttpHandler.class); + private static ActionExecutor actionExecutor = new ActionExecutor<>( + Executors.newFixedThreadPool(5), new IndexAction()); + + public IndexHttpHandler() { + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) { + ctx.flush(); + } + + @SuppressWarnings("deprecation") + @Override + public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) { + if (msg instanceof FullHttpRequest) { + handleHttpRequest(ctx, (FullHttpRequest) msg); + } else { + LOGGER.info("[Ignore] " + msg.getClass().getCanonicalName()); + } + } + + private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest msg) { + if (!msg.uri().startsWith("/SCIDE/Index")) { + try { + DefaultFullHttpResponse fullResponse = new DefaultFullHttpResponse(msg.getProtocolVersion(), OK, + Unpooled.wrappedBuffer(UNSUPPORTED_HTTP_METHOD.getBytes())); + ChannelFuture f = ctx.write(fullResponse); + f.addListener(ChannelFutureListener.CLOSE); + } catch (Exception e) { + e.printStackTrace(); + } + return; + } + HttpRequest req = (HttpRequest) msg; + FullHttpResponse fullResponse = null; + io.netty.handler.codec.http.HttpMethod method = req.getMethod(); + if (method.equals(HttpMethod.GET)) { + QueryStringDecoder decoderQuery = new QueryStringDecoder(req.getUri()); + Map> parame = decoderQuery.parameters(); + JsonObject transfomedParam = new JsonObject(); + for (String key : parame.keySet()) { + List val = parame.get(key); + if (val != null) + transfomedParam.addProperty(key, val.get(0)); + } + handleReq(transfomedParam, ctx, req); + return; + } else if (method.equals(HttpMethod.POST)) { + ByteBuf content = msg.content(); + byte[] reqContent = new byte[content.readableBytes()]; + content.readBytes(reqContent); + String strContent; + try { + strContent = new String(reqContent, "UTF-8"); + JsonObject map = new JsonParser().parse(strContent).getAsJsonObject(); + handleReq(map, ctx, req); + return; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } else { + fullResponse = new DefaultFullHttpResponse(req.getProtocolVersion(), OK, + Unpooled.wrappedBuffer(UNSUPPORTED_HTTP_METHOD.getBytes())); + } + ChannelFuture f = ctx.write(fullResponse); + f.addListener(ChannelFutureListener.CLOSE); + + } + + private void handleReq(JsonObject map, ChannelHandlerContext ctx, HttpRequest req) { + try { + byte[] ret = null; + String action = null; + if (!map.has("action")) { + ret = UNSUPPORTED_ACTION.getBytes(); + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, + Unpooled.wrappedBuffer(ret)); + ChannelFuture f = ctx.write(response); + f.addListener(ChannelFutureListener.CLOSE); + return; + } else + action = map.get("action").getAsString(); + if (action != null) { + HttpResultCallback cb; + if (action.equals("downloadContract")) { + cb = new FileDownloaderCallback(ctx, req); + } else if (map.has("callback")) { + cb = new HttpResultCallback(ctx, map.get("callback").getAsString()); + cb.addHeader("Content-Type", "application/json"); + } else { + cb = new HttpResultCallback(ctx, null); + cb.addHeader("Content-Type", "application/json"); + } + if (map.get("action").getAsString().equals("downloadUUID")) + cb.addHeader("content-disposition", "attachment;filename=encodeduuid.key"); + + actionExecutor.handle(action, map, cb); + } + } catch (IllegalArgumentException e) { + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, + Unpooled.wrappedBuffer(e.getMessage().getBytes())); + ChannelFuture f = ctx.write(response); + f.addListener(ChannelFutureListener.CLOSE); + } catch (Exception e) { + Map ret = new HashMap(); + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + ret.put("msg", bo.toString()); + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, OK, + Unpooled.wrappedBuffer(JsonUtil.toJson(ret).getBytes())); + ChannelFuture f = ctx.write(response); + f.addListener(ChannelFutureListener.CLOSE); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/test/java/org/bdware/server/http/URIHandlerTest.java b/src/test/java/org/bdware/server/http/URIHandlerTest.java new file mode 100644 index 0000000..06f797a --- /dev/null +++ b/src/test/java/org/bdware/server/http/URIHandlerTest.java @@ -0,0 +1,49 @@ +package org.bdware.server.http; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import org.junit.Before; +import org.junit.Test; + +public class URIHandlerTest { + URIHandler handler; + + @Before + public void init() { + handler = new URIHandler(); + handler.register(this); + } + + @URIPath( + method = HttpMethod.OPTIONS, + value = {"/"}) + public void h1(ChannelHandlerContext ctx, FullHttpRequest request) { + return; + } + + @URIPath( + method = HttpMethod.GET, + value = {"/SCIDE/ABC/", "/SCIDE/CEEEE"}) + public void h2(ChannelHandlerContext ctx, FullHttpRequest request) { + return; + } + + @URIPath( + method = HttpMethod.GET, + value = {"/"}) + public void h3(ChannelHandlerContext ctx, FullHttpRequest request) { + return; + } + + @URIPath( + method = HttpMethod.GET, + value = {"/client"}) + public void h4(ChannelHandlerContext ctx, FullHttpRequest request) { + return; + } + + @Test + public void test() { + System.out.println(handler); + } +} diff --git a/src/test/java/org/bdware/server/permission/test/PermissionTest.java b/src/test/java/org/bdware/server/permission/test/PermissionTest.java new file mode 100644 index 0000000..42153f2 --- /dev/null +++ b/src/test/java/org/bdware/server/permission/test/PermissionTest.java @@ -0,0 +1,91 @@ +package org.bdware.server.permission.test; + +import org.bdware.server.permission.Permission; + +import java.util.EnumSet; + +import static org.bdware.server.permission.Permission.*; + +public class PermissionTest { + public static void main(String[] args) { + EnumSet setCenterManager = EnumSet.noneOf(Permission.class); + // 为了便于生成五种角色的Permission 可以用一串set.add()。然后打印出来。 + // 中心管理员 + setCenterManager.add(ApplyRole); + setCenterManager.add(NodeStateList); + setCenterManager.add(AuthNodeManager); + setCenterManager.add(ListAllUsers); + setCenterManager.add(ListApplyUser); + setCenterManager.add(DeleteNodeManager); + setCenterManager.add(ListTrustCluster); + setCenterManager.add(AssignTrustedCluster); + setCenterManager.add(QueryActionLog);// 增加listLog(时间戳) + setCenterManager.add(QueryUserStateLog);// 查看节点日志 + long CenterManager = 0L; + for (Permission p : setCenterManager) { + CenterManager |= p.getValue(); + } + System.out.println("[centerManager]" + String.format("0x%xL", CenterManager)); + EnumSet setNodeManager = EnumSet.noneOf(Permission.class); + // 节点管理员 + setNodeManager.add(ApplyRole); + setNodeManager.add(ListTrustCluster); + setNodeManager.add(QueryUserStateLog); + setNodeManager.add(ConfigureNode); + setNodeManager.add(ManageNode); + setNodeManager.add(GetNodeInfo); + setCenterManager.add(TakeScreenShot); + long NodeManager = 0L;//2248150849 + for (Permission p : setNodeManager) { + NodeManager |= p.getValue(); + } + System.out.println("[NodeManager]" + String.format("0x%xL", NodeManager) + " " + NodeManager); + + EnumSet setContractProvider = EnumSet.noneOf(Permission.class); + // 合约提供者 + setContractProvider.add(ContractCodeStatisticsList); + setContractProvider.add(ConfigureContractPermission); + setContractProvider.add(EditContract); + setContractProvider.add(ListProject); + setContractProvider.add(StaticAnalysis); + setContractProvider.add(Compile); + long ContractProvider = 0L; + for (Permission p : setContractProvider) { + ContractProvider |= p.getValue(); + } + System.out.println("[ContractProvider]" + String.format("0x%xL", ContractProvider)); + EnumSet ContractInstanceManager = EnumSet.noneOf(Permission.class); + // 合约管理者 + ContractInstanceManager.add(AssignTrustedCluster); + ContractInstanceManager.add(ListTrustCluster); + ContractInstanceManager.add(ContractCodeStatisticsList); + ContractInstanceManager.add(StaticAnalysis); + ContractInstanceManager.add(ContractPermissionList); + ContractInstanceManager.add(ListContractProgress); + ContractInstanceManager.add(CheckContractStatus); + ContractInstanceManager.add(ListContractLog); + ContractInstanceManager.add(TimeTravel); + ContractInstanceManager.add(ManualDump); + ContractInstanceManager.add(ManageMemory); + ContractInstanceManager.add(ManageContract); + ContractInstanceManager.add(CreateLedger); + ContractInstanceManager.add(Compile); + long ContractInstanceManagerVAL = 0L; + for (Permission p : ContractInstanceManager) { + ContractInstanceManagerVAL |= p.getValue(); + } + System.out.println("[ContractInstanceManager]" + String.format("0x%xL", ContractInstanceManagerVAL)); + + EnumSet ContractUser = EnumSet.noneOf(Permission.class); + // 合约使用者 + ContractUser.add(ListContractProgress); + ContractUser.add(ContractPermissionList); + ContractUser.add(CheckContractStatus); + ContractUser.add(ListContractLog); + long ContractUserVAL = 0L; + for (Permission p : ContractUser) { + ContractUserVAL |= p.getValue(); + } + System.out.println("[ContractUser]" + String.format("0x%xL", ContractUserVAL)); + } +} diff --git a/src/test/java/org/bdware/server/test/BDLedgerClient.java b/src/test/java/org/bdware/server/test/BDLedgerClient.java new file mode 100644 index 0000000..0f69c89 --- /dev/null +++ b/src/test/java/org/bdware/server/test/BDLedgerClient.java @@ -0,0 +1,84 @@ +package org.bdware.server.test; + +import com.google.protobuf.ByteString; +import org.bdware.bdledger.api.grpc.Client; +import org.bdware.bdledger.api.grpc.pb.CommonProto; +import org.bdware.bdledger.api.grpc.pb.LedgerProto; +import org.bdware.bdledger.api.grpc.pb.QueryProto; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; + +public class BDLedgerClient { + private Client client; + + @Before + public void initClient() { + // + client = new Client("39.104.201.40", 21121); + System.out.println(client.getLedgersSync().getLedgersList()); + } + + public static String byteArray2Str(byte[] byteArray, int offset) { + StringBuilder sb = new StringBuilder(); + for (int j = offset; j < byteArray.length; j++) { + byte b = byteArray[j]; + int i = ((int) b) & 0xff; + sb.append(String.format("%x%x", i >> 4, i & 0xf)); + } + return sb.toString(); + } + + @Test + public void createLedger() { + client.createLedger("default"); + } + + static SecureRandom random = new SecureRandom((System.currentTimeMillis() + "").getBytes()); + + @Test + public void send() { + String mockedFrom = "0xb60e8dd61c5d32be8058bb8eb970870f07233155"; + + LedgerProto.SendTransactionResponse ret2 = + client.sendTransactionSync( + "default", + CommonProto.TransactionType.MESSAGE, + mockedFrom, + random.nextLong(), + mockedFrom, + "Hellooooo".getBytes(StandardCharsets.UTF_8)); + ByteString hash = ret2.getHash(); + System.out.println("[BDLedgerClient] hash:" + byteArray2Str(hash.toByteArray(), 0)); + } + + @Test + public void countBlock() { + // http://069.node.internetapi.cn:21030/SCIDE/CMManager?action=queryDataByHash&hash=30f0b38a845bc3280f0bafa93b2034c8bc494637 + // "ea508a07b79afc03c94a84ff190ca29f1153ef75" + // cb304919522a4acd8f2b23fadf993829ac40795a + QueryProto.GetBlocksResponse blocks = + client.getBlocksSync( + "default", + System.currentTimeMillis() - 23L * 3600L * 1000L, + QueryProto.IncludeTransactions.FULL); + System.out.println("BlockCount:" + blocks.getBlocksCount()); + // GetTransactionByHashResponse result = client.getTransactionByHashSync("test", + // "30f0b38a845bc3280f0bafa93b2034c8bc494637"); + // ByteString bytes = result.getTransaction().getData(); + // System.out.println(new String(bytes.toByteArray())); + } + + @Test + public void queryTransaction() { + // test2 31b50daa8d607c673af5ef449a4d78c70bf952d4 + // bdcontract cb304919522a4acd8f2b23fadf993829ac40795a + QueryProto.GetTransactionByHashResponse result = + client.getTransactionByHashSync( + "default", "78bf9fb27963b26bf2f8d558f20bf44559178b67"); + ByteString bytes = result.getTransaction().getData(); + System.out.println(new String(bytes.toByteArray())); + } +} diff --git a/src/test/java/org/bdware/server/test/ByteHexUtilTest.java b/src/test/java/org/bdware/server/test/ByteHexUtilTest.java new file mode 100644 index 0000000..daccadc --- /dev/null +++ b/src/test/java/org/bdware/server/test/ByteHexUtilTest.java @@ -0,0 +1,14 @@ +package org.bdware.server.test; + +import org.bdware.server.ByteHexUtil; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +public class ByteHexUtilTest { + public static void main(String[] args) throws UnsupportedEncodingException { + String str = "ecb2b0fd0e38b8dbe7cbe1e61ab15afca00da3ba"; + byte[] bytes = ByteHexUtil.decode(str); + System.out.println(URLEncoder.encode("inu3ASBLQE9Pj+hNQjORuK9Amfs=", "utf-8")); + } +} diff --git a/src/test/java/org/bdware/server/test/CMHttpTest.java b/src/test/java/org/bdware/server/test/CMHttpTest.java new file mode 100644 index 0000000..18b43e6 --- /dev/null +++ b/src/test/java/org/bdware/server/test/CMHttpTest.java @@ -0,0 +1,96 @@ +package org.bdware.server.test; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Scanner; + +import com.google.gson.Gson; + +public class CMHttpTest { + public static void main(String[] args) { + // ManagerActionsTest(); + CMActionTest(); + } + + private static void CMActionTest() { + //http_load + String host = "http://127.0.0.1:18000/SCIDE/CMManager?action="; + String url1 = host + "ping"; + System.out.println(httpGet(url1)); + url1 = host + "listContractProcess"; + System.out.println(httpGet(url1)); + url1 = host + "writeDyjs&target=test1120.dyjs&contractID=123&content=empty"; + System.out.println(httpGet(url1)); + url1 = host + "executeContract&contractID=BDCoin&operation=totalSupply&arg=en"; + System.out.println(httpGet(url1)); + url1 = host + "getCodeByID&contractID=DORepo"; + System.out.println(httpGet(url1)); + url1 = host + "getPublicKey"; + System.out.println(httpGet(url1)); + url1 = host + "dumpContract&contractID=DORepo&target=dumTest.dyjs"; + System.out.println(httpGet(url1)); + url1 = host + "loadMemory&contractID=DORepo&target=dumTest.dyjs"; + System.out.println(httpGet(url1)); + url1 = host + "killContractProcess&contractID=abc"; + System.out.println(httpGet(url1)); + url1 = host + "killAllContract"; + System.out.println(httpGet(url1)); + url1 = host + "startContractBatched&fileList=" + URLEncoder.encode("[\"algorithmExample.yjs\",\"AAA.yjs\"]"); + System.out.println(httpGet(url1)); + // url1 = host + "startContractInTempZips"; + // System.out.println(httpGet(url1)); + + } + + private static void ManagerActionsTest() { + String host = "http://127.0.0.1:18000/SCIDE/CMManager?action="; + String url1 = host + "getEncodedUUID"; + System.out.println(httpGet(url1)); + url1 = host + "downloadUUID"; + System.out.println(httpGet(url1)); + url1 = host + "updateConfig&key=projectDir&val=" + + URLEncoder.encode("/Users/huaqiancai/java_workspace/SmartContract/contractExamples"); + System.out.println(httpGet(url1)); + url1 = host + "loadConfig"; + System.out.println(httpGet(url1)); + url1 = host + "getLicenceExpiredDate"; + System.out.println(httpGet(url1)); + url1 = host + "generatePrivateKey"; + System.out.println(httpGet(url1)); + + } + + static class Result { + int resposeCode; + String response; + } + + public static String httpGet(String str) { + System.out.println("JavaScriptEntry httpGet:" + str); + Result r = new Result(); + try { + URL url = new URL(str); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + r.resposeCode = connection.getResponseCode(); + InputStream input = connection.getInputStream(); + Scanner sc = new Scanner(input); + StringBuilder sb = new StringBuilder(); + for (; sc.hasNextLine();) { + sb.append(sc.nextLine()).append("\n"); + } + sc.close(); + r.response = sb.toString(); + return new Gson().toJson(r); + } catch (Throwable e) { + r.resposeCode = 505; + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + r.response = bo.toString(); + return new Gson().toJson(r); + } + } +} diff --git a/src/test/java/org/bdware/server/test/GsonParseTest.java b/src/test/java/org/bdware/server/test/GsonParseTest.java new file mode 100644 index 0000000..fea1e5f --- /dev/null +++ b/src/test/java/org/bdware/server/test/GsonParseTest.java @@ -0,0 +1,21 @@ +package org.bdware.server.test; + +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; +import org.bdware.sc.bean.ContractDesp; + +public class GsonParseTest { + public static void main(String[] args) { + String jsonStr = "{\"action\":\"updateContract\",\"contracts\":\"[{\\\"contractID\\\":\\\"-1306108766\\\",\\\"contractName\\\":\\\"EventSuberAtCHQ\\\",\\\"events\\\":[\\\"def\\\"],\\\"exportedFunctions\\\":[{\\\"annotations\\\":[{\\\"type\\\":\\\"LogType\\\",\\\"args\\\":[\\\"\\\\\\\"Arg\\\\\\\"\\\"]}],\\\"functionName\\\":\\\"init\\\"},{\\\"annotations\\\":[{\\\"type\\\":\\\"LogType\\\",\\\"args\\\":[\\\"\\\\\\\"Arg\\\\\\\"\\\"]}],\\\"functionName\\\":\\\"handler\\\"}]}]\"}\n"; + JsonObject jo = new JsonParser().parse(jsonStr).getAsJsonObject(); + List contracts = new Gson().fromJson(jo.get("contracts").getAsString(), + new TypeToken>() { + }.getType()); + System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(contracts)); + } +} diff --git a/src/test/java/org/bdware/server/test/HttpPostFormTest.java b/src/test/java/org/bdware/server/test/HttpPostFormTest.java new file mode 100644 index 0000000..79ed68e --- /dev/null +++ b/src/test/java/org/bdware/server/test/HttpPostFormTest.java @@ -0,0 +1,111 @@ +package org.bdware.server.test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +public class HttpPostFormTest { + + public static void postForm(String url, Map params) { + + String responseMessage = ""; + StringBuffer response = new StringBuffer(); + HttpURLConnection httpConnection = null; + OutputStreamWriter out = null; + BufferedReader reader = null; + try { + URL urlPost = new URL(url); + httpConnection = (HttpURLConnection) urlPost.openConnection(); + httpConnection.setDoOutput(true); + httpConnection.setDoInput(true); + httpConnection.setRequestMethod("POST"); + httpConnection.setUseCaches(false); + httpConnection.setInstanceFollowRedirects(true); + httpConnection.setRequestProperty("Connection", "Keep-Alive"); + httpConnection.setRequestProperty("Charset", "UTF-8"); + // 设置边界 + String BOUNDARY = "----------" + System.currentTimeMillis(); + // httpConnection.setRequestProperty("Content-Type", "multipart/form-data; + // boundary=" + BOUNDARY); + httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;boundary=" + BOUNDARY); + + // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成, + // 要注意的是connection.getOutputStream会隐含的进行connect。 + // 实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。 + + httpConnection.connect(); + out = new OutputStreamWriter(httpConnection.getOutputStream(), "UTF-8"); + + StringBuffer sb = new StringBuffer(); + int count = params.size(); + for (String key : params.keySet()) { + sb.append(key + "=" + URLEncoder.encode(params.get(key))); + count--; + if (count > 0) + sb.append("&"); + } + out.write(sb.toString()); + System.out.println("send_url:" + url); + System.out.println("send_data:" + sb.toString()); + // flush and close + out.flush(); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (null != out) { + out.close(); + } + if (null != reader) { + reader.close(); + } + if (null != httpConnection) { + httpConnection.disconnect(); + } + } catch (Exception e2) { + e2.printStackTrace(); + } + } + + try { + reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream(), "UTF-8")); + while ((responseMessage = reader.readLine()) != null) { + response.append(responseMessage); + response.append("\n"); + } + + if (!"failure".equals(response.toString())) { + System.out.println("success"); + } else { + System.out.println("failue"); + } + // 将该url的配置信息缓存起来 + System.out.println(response.toString()); + System.out.println(httpConnection.getResponseCode()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + String url = "http://47.106.38.23:13081/register"; + + Map params = new HashMap(); + String sucFix = System.currentTimeMillis() + "_ContractLog"; + params.put("DOI", "86.5000.470/" + sucFix); + params.put("Description", "Contract Log"); + params.put("Interface", ""); + params.put("Address", ""); + params.put("PublicKey", ""); + params.put("Signature", ""); + // http://47.106.38.23:8080/idsystem/doDetail.html?doi=86.5000.470/1570626378959_ContractLog + postForm(url, params); + } +} diff --git a/src/test/java/org/bdware/server/test/LongParseTest.java b/src/test/java/org/bdware/server/test/LongParseTest.java new file mode 100644 index 0000000..34e52c7 --- /dev/null +++ b/src/test/java/org/bdware/server/test/LongParseTest.java @@ -0,0 +1,8 @@ +package org.bdware.server.test; + +public class LongParseTest { + public static void main(String[] args) { + String str = "6151".toUpperCase(); + Long.parseUnsignedLong(str, 16); + } +} diff --git a/src/test/java/org/bdware/server/test/NCHttpTest.java b/src/test/java/org/bdware/server/test/NCHttpTest.java new file mode 100644 index 0000000..dd48974 --- /dev/null +++ b/src/test/java/org/bdware/server/test/NCHttpTest.java @@ -0,0 +1,84 @@ +package org.bdware.server.test; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Scanner; + +import com.google.gson.Gson; + +public class NCHttpTest { + public static void main(String[] args) { + // ManagerActionsTest(); + CMActionTest(); + } + + private static void CMActionTest() { + String host = "http://127.0.0.1:18001/SCIDE/NodeCenter?action="; + String url1 = host + "ping"; + System.out.println(httpGet(url1)); + url1 = host + "setNodeID"; + System.out.println(httpGet(url1)); + url1 = host + "listCMInfo"; + System.out.println(httpGet(url1)); + url1 = host + "updateContract"; + System.out.println(httpGet(url1)); + + url1 = host + "executeContractOnOtherNodes&requestID=33333&contractRequest={\"contractID\":\"BDCoin\",\"action\":\"totalSupply\",\"arg\":\"n\"}"; + System.out.println(httpGet(url1)); + // url1 = host + "startContractInTempZips"; + // System.out.println(httpGet(url1)); + + } + + private static void ManagerActionsTest() { + String host = "http://127.0.0.1:18000/SCIDE/CMManager?action="; + String url1 = host + "getEncodedUUID"; + System.out.println(httpGet(url1)); + url1 = host + "downloadUUID"; + System.out.println(httpGet(url1)); + url1 = host + "updateConfig&key=projectDir&val=" + + URLEncoder.encode("/Users/huaqiancai/java_workspace/SmartContract/contractExamples"); + System.out.println(httpGet(url1)); + url1 = host + "loadConfig"; + System.out.println(httpGet(url1)); + url1 = host + "getLicenceExpiredDate"; + System.out.println(httpGet(url1)); + url1 = host + "generatePrivateKey"; + System.out.println(httpGet(url1)); + + } + + static class Result { + int resposeCode; + String response; + } + + public static String httpGet(String str) { + System.out.println("JavaScriptEntry httpGet:" + str); + Result r = new Result(); + try { + URL url = new URL(str); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + r.resposeCode = connection.getResponseCode(); + InputStream input = connection.getInputStream(); + Scanner sc = new Scanner(input); + StringBuilder sb = new StringBuilder(); + for (; sc.hasNextLine();) { + sb.append(sc.nextLine()).append("\n"); + } + sc.close(); + r.response = sb.toString(); + return new Gson().toJson(r); + } catch (Throwable e) { + r.resposeCode = 505; + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + r.response = bo.toString(); + return new Gson().toJson(r); + } + } +} diff --git a/src/test/java/org/bdware/server/test/StringTest.java b/src/test/java/org/bdware/server/test/StringTest.java new file mode 100644 index 0000000..e86fe3f --- /dev/null +++ b/src/test/java/org/bdware/server/test/StringTest.java @@ -0,0 +1,19 @@ +package org.bdware.server.test; + +public class StringTest { + public static void main(String[] arg) { + // String str = "\\manifest.json\\dadad\\daaa"; + // System.out.println(str.replaceAll("\\\\", (byte)"/")); + byte[] arr = new byte[] { (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x89, (byte) 0x7f, (byte) 0x51, (byte) 0x8c, (byte) 0x50, + (byte) 0xbb, (byte) 0xd0, (byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xe9, (byte) 0xf4, (byte) 0xf8, + (byte) 0xfc, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x89, (byte) 0x7f, (byte) 0x51, (byte) 0x8c, (byte) 0x3e, (byte) 0xf4, + (byte) 0x8, (byte) 0x40, (byte) 0x9f, (byte) 0x84, (byte) 0x50, (byte) 0xbb, (byte) 0xd0, (byte) 0x7f, + (byte) 0xff, (byte) 0xff, (byte) 0xe9, (byte) 0xf4, (byte) 0xf8, (byte) 0xfc, (byte) 0xf8, (byte) 0xfc, + (byte) 0x0 }; + System.out.println(new String(arr)); + String str = "042668227e8283cc132863cf7b83489f81056c87a19f878515d6787db7f86da7145ae05926b8e8053e59f93afdddc8705d7e17a5293b60a124a2e842d3c77cf74f"; + System.out.println(str.hashCode()); + } +}