mirror of
https://gitee.com/BDWare/front-base
synced 2025-01-09 17:34:01 +00:00
initial commit
This commit is contained in:
parent
454ee4d5c9
commit
2cf6886649
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/build
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
|
33
build.gradle
Normal file
33
build.gradle
Normal file
@ -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'
|
||||
}
|
52
src/main/src/org/bdware/server/ByteHexUtil.java
Normal file
52
src/main/src/org/bdware/server/ByteHexUtil.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
108
src/main/src/org/bdware/server/CMDConf.java
Normal file
108
src/main/src/org/bdware/server/CMDConf.java
Normal file
@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
99
src/main/src/org/bdware/server/Entry.java
Normal file
99
src/main/src/org/bdware/server/Entry.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
20
src/main/src/org/bdware/server/action/Action.java
Normal file
20
src/main/src/org/bdware/server/action/Action.java
Normal file
@ -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 {};
|
||||
}
|
173
src/main/src/org/bdware/server/action/ActionExecutor.java
Normal file
173
src/main/src/org/bdware/server/action/ActionExecutor.java
Normal file
@ -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<T, U> {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ActionExecutor.class);
|
||||
// ---------- use for profiling
|
||||
static Map<String, Map<String, AtomicInteger>> allData = new ConcurrentHashMap<>();
|
||||
public ExecutorService executor;
|
||||
// private Profiler profiler = new Profiler();
|
||||
public long permission;
|
||||
Map<String, AtomicInteger> staticData;
|
||||
private Map<String, Pair<Method, Object>> 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<String> getAECallerSet() {
|
||||
return allData.keySet();
|
||||
}
|
||||
|
||||
public static Map<String, AtomicInteger> getStatistic(String caller) {
|
||||
return allData.get(caller);
|
||||
}
|
||||
|
||||
public static Map<String, Map<String, AtomicInteger>> getAllData() {
|
||||
return allData;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public Map<String, AtomicInteger> 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<String, Pair<Method, Object>> 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<Method, Object> 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, U> {
|
||||
T first;
|
||||
U second;
|
||||
|
||||
public Pair(T f, U s) {
|
||||
first = f;
|
||||
second = s;
|
||||
}
|
||||
|
||||
public T first() {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<String, String> 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:./
|
||||
|
||||
|
||||
* */
|
16
src/main/src/org/bdware/server/action/Result.java
Normal file
16
src/main/src/org/bdware/server/action/Result.java
Normal file
@ -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="";
|
||||
}
|
||||
}
|
126
src/main/src/org/bdware/server/action/SyncResult.java
Normal file
126
src/main/src/org/bdware/server/action/SyncResult.java
Normal file
@ -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<String, ResultCallback> 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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
157
src/main/src/org/bdware/server/http/HttpFileHandleAdapter.java
Normal file
157
src/main/src/org/bdware/server/http/HttpFileHandleAdapter.java
Normal file
@ -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<FullHttpRequest> {
|
||||
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));
|
||||
}
|
||||
}
|
36
src/main/src/org/bdware/server/http/HttpMethod.java
Normal file
36
src/main/src/org/bdware/server/http/HttpMethod.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
113
src/main/src/org/bdware/server/http/URIHandler.java
Normal file
113
src/main/src/org/bdware/server/http/URIHandler.java
Normal file
@ -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<io.netty.handler.codec.http.HttpMethod, List<Tuple<String, Method, Object>>> 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<Tuple<String, Method, Object>> handlerList = getOrCreate(method);
|
||||
for (String str : path.value()) {
|
||||
m.setAccessible(true);
|
||||
handlerList.add(new Tuple<>(str, m, obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (List<Tuple<String, Method, Object>> handlerList : handlers.values()) {
|
||||
sortHandlerList(handlerList);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Tuple<String, Method, Object>> getOrCreate(HttpMethod method) {
|
||||
return handlers.computeIfAbsent(method.get(), k -> new ArrayList<>());
|
||||
}
|
||||
|
||||
private void sortHandlerList(List<Tuple<String, Method, Object>> 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<Tuple<String, Method, Object>> handlerList = handlers.get(msg.method());
|
||||
for (Tuple<String, Method, Object> 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<String, Method, Object> t : handlers.get(m)) {
|
||||
String className = t.u.getDeclaringClass().getSimpleName();
|
||||
sbl.append("\t\t").append(t.t.isEmpty() ? "<null>" : 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, U, S> {
|
||||
T t;
|
||||
U u;
|
||||
S s;
|
||||
|
||||
Tuple(T t, U u, S s) {
|
||||
this.t = t;
|
||||
this.u = u;
|
||||
this.s = s;
|
||||
}
|
||||
}
|
||||
}
|
13
src/main/src/org/bdware/server/http/URIPath.java
Normal file
13
src/main/src/org/bdware/server/http/URIPath.java
Normal file
@ -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;
|
||||
}
|
9
src/main/src/org/bdware/server/nodecenter/Response.java
Normal file
9
src/main/src/org/bdware/server/nodecenter/Response.java
Normal file
@ -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;
|
||||
}
|
14
src/main/src/org/bdware/server/nodecenter/ResultBack.java
Normal file
14
src/main/src/org/bdware/server/nodecenter/ResultBack.java
Normal file
@ -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 = "";
|
||||
}
|
||||
}
|
5
src/main/src/org/bdware/server/nodecenter/UserMySQL.java
Normal file
5
src/main/src/org/bdware/server/nodecenter/UserMySQL.java
Normal file
@ -0,0 +1,5 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
public class UserMySQL {
|
||||
|
||||
}
|
@ -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<ContractDesp> 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<String, String> json) {
|
||||
String jsonStr = json.get("contracts");
|
||||
contracts = JsonUtil.fromJson(jsonStr, new TypeToken<List<ContractDesp>>() {
|
||||
}.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;
|
||||
|
||||
}
|
||||
|
||||
}
|
93
src/main/src/org/bdware/server/permission/Permission.java
Normal file
93
src/main/src/org/bdware/server/permission/Permission.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
43
src/main/src/org/bdware/server/permission/Role.java
Normal file
43
src/main/src/org/bdware/server/permission/Role.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -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<ByteBuf> {
|
||||
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);
|
||||
}
|
||||
}
|
17
src/main/src/org/bdware/server/ws/DelimiterCodec.java
Normal file
17
src/main/src/org/bdware/server/ws/DelimiterCodec.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
100
src/main/src/org/bdware/server/ws/WebSocketIndexPageHandler.java
Normal file
100
src/main/src/org/bdware/server/ws/WebSocketIndexPageHandler.java
Normal file
@ -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<FullHttpRequest> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
105
src/main/src/org/bdware/server/ws/WebSocketServerIndexPage.java
Normal file
105
src/main/src/org/bdware/server/ws/WebSocketServerIndexPage.java
Normal file
@ -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 =
|
||||
"<html><head><title>Web Socket Test</title></head>"
|
||||
+ NEWLINE
|
||||
+ "<body>"
|
||||
+ NEWLINE
|
||||
+ "<script type=\"text/javascript\">"
|
||||
+ NEWLINE
|
||||
+ "var socket;"
|
||||
+ NEWLINE
|
||||
+ "if (!window.WebSocket) {"
|
||||
+ NEWLINE
|
||||
+ " window.WebSocket = window.MozWebSocket;"
|
||||
+ NEWLINE
|
||||
+ '}'
|
||||
+ NEWLINE
|
||||
+ "if (window.WebSocket) {"
|
||||
+ NEWLINE
|
||||
+ " socket = new WebSocket(\""
|
||||
+ webSocketLocation
|
||||
+ "\");"
|
||||
+ NEWLINE
|
||||
+ " socket.onmessage = function(event) {"
|
||||
+ NEWLINE
|
||||
+ " var ta = document.getElementById('responseText');"
|
||||
+ NEWLINE
|
||||
+ " ta.value = ta.value + '\\n' + event.data"
|
||||
+ NEWLINE
|
||||
+ " };"
|
||||
+ NEWLINE
|
||||
+ " socket.onopen = function(event) {"
|
||||
+ NEWLINE
|
||||
+ " var ta = document.getElementById('responseText');"
|
||||
+ NEWLINE
|
||||
+ " ta.value = \"Web Socket opened!\";"
|
||||
+ NEWLINE
|
||||
+ " };"
|
||||
+ NEWLINE
|
||||
+ " socket.onclose = function(event) {"
|
||||
+ NEWLINE
|
||||
+ " var ta = document.getElementById('responseText');"
|
||||
+ NEWLINE
|
||||
+ " ta.value = ta.value + \"Web Socket closed\"; "
|
||||
+ NEWLINE
|
||||
+ " };"
|
||||
+ NEWLINE
|
||||
+ "} else {"
|
||||
+ NEWLINE
|
||||
+ " alert(\"Your browser does not support Web Socket.\");"
|
||||
+ NEWLINE
|
||||
+ '}'
|
||||
+ NEWLINE
|
||||
+ NEWLINE
|
||||
+ "function send(message) {"
|
||||
+ NEWLINE
|
||||
+ " if (!window.WebSocket) { return; }"
|
||||
+ NEWLINE
|
||||
+ " if (socket.readyState == WebSocket.OPEN) {"
|
||||
+ NEWLINE
|
||||
+ " socket.send(message);"
|
||||
+ NEWLINE
|
||||
+ " } else {"
|
||||
+ NEWLINE
|
||||
+ " alert(\"The socket is not open.\");"
|
||||
+ NEWLINE
|
||||
+ " }"
|
||||
+ NEWLINE
|
||||
+ '}'
|
||||
+ NEWLINE
|
||||
+ "</script>"
|
||||
+ NEWLINE
|
||||
+ "<form onsubmit=\"return false;\">"
|
||||
+ NEWLINE
|
||||
+ "<input type=\"text\" name=\"message\" value=\"Hello, World!\"/>"
|
||||
+ "<input type=\"button\" value=\"Send Web Socket Data\""
|
||||
+ NEWLINE
|
||||
+ " onclick=\"send(this.form.message.value)\" />"
|
||||
+ NEWLINE
|
||||
+ "<h3>Output</h3>"
|
||||
+ NEWLINE
|
||||
+ "<textarea id=\"responseText\" style=\"width:500px;height:300px;\"></textarea>"
|
||||
+ NEWLINE
|
||||
+ "</form>"
|
||||
+ NEWLINE
|
||||
+ "</body>"
|
||||
+ NEWLINE
|
||||
+ "</html>"
|
||||
+ NEWLINE;
|
||||
return Unpooled.wrappedBuffer(str.getBytes());
|
||||
}
|
||||
|
||||
private WebSocketServerIndexPage() {
|
||||
// Unused
|
||||
}
|
||||
}
|
8
src/main/src/resources/log4j.properties
Normal file
8
src/main/src/resources/log4j.properties
Normal file
@ -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
|
60
src/main/thirdparty/org/bdware/server/IndexServer.java
vendored
Normal file
60
src/main/thirdparty/org/bdware/server/IndexServer.java
vendored
Normal file
@ -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<SocketChannel>() {
|
||||
@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();
|
||||
}
|
||||
}
|
||||
}
|
230
src/main/thirdparty/org/bdware/server/action/IndexAction.java
vendored
Normal file
230
src/main/thirdparty/org/bdware/server/action/IndexAction.java
vendored
Normal file
@ -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<String, LenVarTimeSerialIndex2> 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<byte[]> 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<byte[]> 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<byte[]> 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<Data> list;
|
||||
}
|
||||
|
||||
static class Data {
|
||||
long date;
|
||||
String data;
|
||||
|
||||
public Data(byte[] bytes) {
|
||||
date = HashUtil.bytes2Long(bytes);
|
||||
data = HashUtil.byteArray2Str(bytes, 8);
|
||||
}
|
||||
}
|
||||
}
|
157
src/main/thirdparty/org/bdware/server/http/IndexHttpHandler.java
vendored
Normal file
157
src/main/thirdparty/org/bdware/server/http/IndexHttpHandler.java
vendored
Normal file
@ -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<HttpObject> {
|
||||
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<ResultCallback, JsonObject> 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<String, List<String>> parame = decoderQuery.parameters();
|
||||
JsonObject transfomedParam = new JsonObject();
|
||||
for (String key : parame.keySet()) {
|
||||
List<String> 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<String, String> ret = new HashMap<String, String>();
|
||||
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();
|
||||
}
|
||||
}
|
49
src/test/java/org/bdware/server/http/URIHandlerTest.java
Normal file
49
src/test/java/org/bdware/server/http/URIHandlerTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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<Permission> 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<Permission> 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<Permission> 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<Permission> 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<Permission> 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));
|
||||
}
|
||||
}
|
84
src/test/java/org/bdware/server/test/BDLedgerClient.java
Normal file
84
src/test/java/org/bdware/server/test/BDLedgerClient.java
Normal file
@ -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()));
|
||||
}
|
||||
}
|
14
src/test/java/org/bdware/server/test/ByteHexUtilTest.java
Normal file
14
src/test/java/org/bdware/server/test/ByteHexUtilTest.java
Normal file
@ -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"));
|
||||
}
|
||||
}
|
96
src/test/java/org/bdware/server/test/CMHttpTest.java
Normal file
96
src/test/java/org/bdware/server/test/CMHttpTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
21
src/test/java/org/bdware/server/test/GsonParseTest.java
Normal file
21
src/test/java/org/bdware/server/test/GsonParseTest.java
Normal file
@ -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<ContractDesp> contracts = new Gson().fromJson(jo.get("contracts").getAsString(),
|
||||
new TypeToken<List<ContractDesp>>() {
|
||||
}.getType());
|
||||
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(contracts));
|
||||
}
|
||||
}
|
111
src/test/java/org/bdware/server/test/HttpPostFormTest.java
Normal file
111
src/test/java/org/bdware/server/test/HttpPostFormTest.java
Normal file
@ -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<String, String> 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<String, String> params = new HashMap<String, String>();
|
||||
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);
|
||||
}
|
||||
}
|
8
src/test/java/org/bdware/server/test/LongParseTest.java
Normal file
8
src/test/java/org/bdware/server/test/LongParseTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
84
src/test/java/org/bdware/server/test/NCHttpTest.java
Normal file
84
src/test/java/org/bdware/server/test/NCHttpTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
19
src/test/java/org/bdware/server/test/StringTest.java
Normal file
19
src/test/java/org/bdware/server/test/StringTest.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user