From 8fa064ee8a911e389c6e3ebd4c6d6b38b01004b5 Mon Sep 17 00:00:00 2001 From: CaiHQ Date: Thu, 30 Mar 2023 14:58:43 +0800 Subject: [PATCH] update bdrepo support --- build.gradle | 4 +- .../java/org/bdware/server/CMHttpServer.java | 50 +++--- src/main/java/org/bdware/server/DOAConf.java | 6 - .../java/org/bdware/server/GlobalConf.java | 57 ++++--- .../org/bdware/server/action/CMActions.java | 54 +++++-- .../bdware/server/action/ManagerActions.java | 9 +- .../p2p/MasterServerTransferAction.java | 3 - .../action/p2p/_UNUSED_ExecutionAction.java | 1 - .../org/bdware/server/doip/BCOManager.java | 130 ++++++++++++++++ .../doip/ContractRepositoryHandler.java | 146 ++++++++++++++++-- .../server/doip/ContractRepositoryMain.java | 28 ++-- .../server/doip/ContractRepositoryServer.java | 5 - .../org/bdware/server/http/CMHttpHandler.java | 4 +- src/test/java/org/bdware/server/DOIPTest.java | 63 -------- .../org/bdware/server/DoipClientTest.java | 37 +++++ .../bdware/server/doip/BCOManagerTest.java | 36 +++++ 16 files changed, 462 insertions(+), 171 deletions(-) delete mode 100644 src/main/java/org/bdware/server/DOAConf.java create mode 100644 src/main/java/org/bdware/server/doip/BCOManager.java delete mode 100644 src/main/java/org/bdware/server/doip/ContractRepositoryServer.java delete mode 100644 src/test/java/org/bdware/server/DOIPTest.java create mode 100644 src/test/java/org/bdware/server/DoipClientTest.java create mode 100644 src/test/java/org/bdware/server/doip/BCOManagerTest.java diff --git a/build.gradle b/build.gradle index 80a7f09..4ab8b6f 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,9 @@ dependencies { implementation 'io.grpc:grpc-all:1.43.1' implementation 'org.apache.velocity:velocity-engine-core:2.3' implementation 'com.nimbusds:nimbus-jose-jwt:9.10' - implementation 'org.bdware.doip:doip-sdk:1.1.0' + implementation 'org.bdware.doip:doip-sdk:1.3.8' + implementation 'org.bdware.doip:doip-audit-tool:1.1.9' + implementation 'org.bdware.doip:bdosclient:0.0.1' implementation fileTree(dir: 'lib', include: '*.jar') testImplementation 'junit:junit:4.13.2' implementation group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: '2.0.50.Final' diff --git a/src/main/java/org/bdware/server/CMHttpServer.java b/src/main/java/org/bdware/server/CMHttpServer.java index 403b896..1e0d5a1 100644 --- a/src/main/java/org/bdware/server/CMHttpServer.java +++ b/src/main/java/org/bdware/server/CMHttpServer.java @@ -17,13 +17,17 @@ import io.netty.handler.ssl.OptionalSslHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.stream.ChunkedWriteHandler; +import io.netty.util.internal.StringUtil; import io.prometheus.client.exporter.HTTPServer; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.Configurator; -import org.bdware.sc.*; +import org.bdware.sc.ContractClient; +import org.bdware.sc.ContractManager; +import org.bdware.sc.ContractPort; +import org.bdware.sc.RecoverMechTimeRecorder; import org.bdware.sc.bean.Contract; import org.bdware.sc.bean.ContractExecType; import org.bdware.sc.db.CMTables; @@ -66,22 +70,23 @@ public class CMHttpServer { } private static void configServer(CMDConf cmdConf) throws IOException { - if (cmdConf.disableDoRepo) { - DoConfig.callContractUsingDOI = false; + GlobalConf.DOAConf doaConf = new GlobalConf.DOAConf(); + if (cmdConf.doipPort != -1) { + doaConf.doipAddress = "tcp://" + cmdConf.ip + ":" + cmdConf.doipPort; + } else { + doaConf.doipAddress = "tcp://" + cmdConf.ip + ":" + (cmdConf.servicePort + 2); } - GlobalConf.instance.isLAN = cmdConf.isLAN; - if (!cmdConf.doipCertPath.isEmpty()) { - String[] conf = cmdConf.doipCertPath.split(":"); -// DOAConf.certPath = conf[0]; -// DOAConf.certPassword = conf[1]; + if (!StringUtil.isNullOrEmpty(cmdConf.repoDoid)) { + doaConf.repoDoid = cmdConf.repoDoid; } + if (!StringUtil.isNullOrEmpty(cmdConf.repoName)) { + doaConf.repoName = cmdConf.repoName; + } + if (!StringUtil.isNullOrEmpty(cmdConf.lhsAddress)) { + doaConf.lhsAddress = cmdConf.lhsAddress; + } + GlobalConf.initDOAConfig(doaConf); - if (!cmdConf.doipUserHandle.isEmpty()) { - DOAConf.repoDoid = cmdConf.doipUserHandle; - } - if (!cmdConf.doipLhsAddress.isEmpty()) { - DOAConf.lhsAddress = cmdConf.doipLhsAddress; - } if (cmdConf.withBdledgerServer) { ContractManager.threadPool.execute( () -> NetworkManager.instance.initP2P(cmdConf.servicePort + 4)); @@ -104,7 +109,7 @@ public class CMHttpServer { if (cmdConf.enableEventPersistence) { ContractManager.eventPersistenceEnabled = true; } - if (!cmdConf.enableSsl.isEmpty()) { + if (!StringUtil.isNullOrEmpty(cmdConf.enableSsl)) { try { String[] filePaths = cmdConf.enableSsl.split(":"); File chainedFile = new File(filePaths[0]), keyFile = new File(filePaths[1]); @@ -139,7 +144,7 @@ public class CMHttpServer { TCPClientFrameHandler.clientToAgentPlugins = parseStrAsList(cmdConf.clientToAgentPlugins); NodeCenterClientHandler.clientToClusterPlugins = parseStrAsList(cmdConf.clientToClusterPlugins); org.bdware.units.tcp.TCPClientFrameHandler.tcpPlugins = parseStrAsList(cmdConf.tcpPlugins); - if (!cmdConf.debug.isEmpty()) { + if (!StringUtil.isNullOrEmpty(cmdConf.debug)) { try { String[] classes = cmdConf.debug.split(","); for (String clz : classes) { @@ -278,16 +283,18 @@ public class CMHttpServer { } } - start(cmdConf.ip, cmdConf.servicePort, cmdConf); + GlobalConf.initIpPort(cmdConf.ip + ":" + cmdConf.servicePort); + GlobalConf.initMasterAddress(cmdConf.ip + ":" + (cmdConf.servicePort + 1)); + start(cmdConf.servicePort); } - public static void start(String ip, int port, CMDConf cmdConf) throws IOException { + public static void start(int port) throws IOException { LOGGER.info("start server at:" + port); - GlobalConf.initMasterAddress(ip + ":" + (port + 1)); - GlobalConf.initIpPort(ip + ":" + port); LOGGER.debug("dir:" + new File("./").getAbsolutePath()); + + new CMHttpServer(port).start(); - ContractRepositoryMain.start(); + //never reach here!! } /** @@ -321,6 +328,7 @@ public class CMHttpServer { } else { ContractManager.cPort = new ContractPort(1615); } + ContractRepositoryMain.start(); final CMHttpHandler serverHandler = new CMHttpHandler(); EventLoopGroup bossGroup = new NioEventLoopGroup(1); NettyConnectServerHandler trafficSharp = diff --git a/src/main/java/org/bdware/server/DOAConf.java b/src/main/java/org/bdware/server/DOAConf.java deleted file mode 100644 index 8b67c75..0000000 --- a/src/main/java/org/bdware/server/DOAConf.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.bdware.server; - -public class DOAConf { - public static String lhsAddress; - public static String repoDoid; -} diff --git a/src/main/java/org/bdware/server/GlobalConf.java b/src/main/java/org/bdware/server/GlobalConf.java index 5646e01..9c9c139 100644 --- a/src/main/java/org/bdware/server/GlobalConf.java +++ b/src/main/java/org/bdware/server/GlobalConf.java @@ -24,6 +24,17 @@ public class GlobalConf { private static final Logger LOGGER = LogManager.getLogger(GlobalConf.class); public static GlobalConf instance = init(); + + + public static class DOAConf { + + public String doipAddress; + public String lhsAddress = ""; + public String repoDoid = ""; + public String repoName = ""; + } + + public DOAConf doaConf; public String projectDir; // 从configDB读取;默认./ProjectDir/ // 对于public-->SCIDEProjectDir/public/ // 对于private-->SCIDEProjectDir/private/4567856786789/ @@ -40,6 +51,8 @@ public class GlobalConf { public String publicCompiledDir; public String privateDir; public String privateCompiledDir; + public String bcoDir; + public String memoryDir; public String masterAddress; public String ipPort; @@ -47,6 +60,7 @@ public class GlobalConf { private String nodeCenterUrl; // 从ConfigDB读。 private String nodeCenterWSUrl; + private static GlobalConf init() { java.util.logging.Logger.getLogger(org.bdware.bdledger.api.grpc.Client.class.getName()) .setLevel(Level.OFF); @@ -126,11 +140,7 @@ public class GlobalConf { KeyValueDBUtil.instance.setValue(dbName, "nodeName", deviceName.substring(0, 10)); KeyValueDBUtil.instance.setValue(dbName, "masterAddress", "null"); KeyValueDBUtil.instance.setValue(dbName, "ipPort", "null"); - JsonObject doipConfig = new JsonObject(); - doipConfig.addProperty("lhsAddress", "tcp://127.0.0.1:2641"); - doipConfig.addProperty("repoDoid", "bdware.trusted.test/Repo." + conf.keyPair.getPublicKeyStr().substring(0, 6)); - KeyValueDBUtil.instance.setValue(dbName, "doipConfig", doipConfig.toString()); - KeyValueDBUtil.instance.setValue(dbName, "nodeCenter", "ws://127.0.0.1:18002"); + KeyValueDBUtil.instance.setValue(dbName, "nodeCenter", "ws://127.0.0.1:18002"); KeyValueDBUtil.instance.setValue( dbName, "datachainConf", @@ -142,6 +152,7 @@ public class GlobalConf { } conf.projectDir = KeyValueDBUtil.instance.getValue(dbName, "projectDir"); + conf.bcoDir = conf.projectDir+"/bco"; conf.publicDir = KeyValueDBUtil.instance.getValue(dbName, "projectDir") + "/public"; conf.ADSPDir = KeyValueDBUtil.instance.getValue(dbName, "projectDir") + "/ADSPDir"; conf.publicCompiledDir = @@ -159,12 +170,12 @@ public class GlobalConf { conf.masterAddress = KeyValueDBUtil.instance.getValue(dbName, "masterAddress"); conf.nodeCenterUrl = KeyValueDBUtil.instance.getValue(dbName, "nodeCenter"); conf.nodeCenterWSUrl = KeyValueDBUtil.instance.getValue(dbName, "nodeCenterWS"); - conf.peerID = KeyValueDBUtil.instance.getValue(dbName, "peerID"); conf.keyPairStr = KeyValueDBUtil.instance.getValue(dbName, "keyPairStr"); // logger.debug("keyPairStr" + conf.keyPairStr); conf.keyPair = SM2KeyPair.fromJson(conf.keyPairStr); - loadDOAConfig(KeyValueDBUtil.instance.getValue(dbName, "doipConfig")); + conf.doaConf = new DOAConf(); + loadDOAConfig(conf.doaConf, KeyValueDBUtil.instance.getValue(dbName, "doipConfig")); } catch (Exception e) { LOGGER.error(e.getMessage()); LOGGER.debug(ExceptionUtil.exceptionToString(e)); @@ -224,23 +235,19 @@ public class GlobalConf { return conf; } - private static void loadDOAConfig(String val) { + private static void loadDOAConfig(DOAConf doaConf, String val) { try { - JsonObject doipConfig = JsonUtil.parseStringAsJsonObject(val); - DOAConf.lhsAddress = doipConfig.get("lhsAddress").getAsString(); - DOAConf.repoDoid = doipConfig.get("repoDoid").getAsString(); - //TODO 这个怎么获取?要通过啥来获取自己的repoDoid呢? - //所以现在的lhsAddress暂时没起作用。 + if (val != null && !"null".equals(val)) { + JsonObject doipConfig = JsonUtil.parseStringAsJsonObject(val); + doaConf.lhsAddress = doipConfig.get("lhsAddress").getAsString(); + doaConf.repoDoid = doipConfig.get("repoDoid").getAsString(); + doaConf.doipAddress = doipConfig.get("doipAddress").getAsString(); + doaConf.repoName = doipConfig.get("repoName").getAsString(); + } } catch (Exception e) { } } - public static String getDOAConfig() { - JsonObject doipConfig = new JsonObject(); - doipConfig.addProperty("lhsAddress", DOAConf.lhsAddress); - doipConfig.addProperty("repoDoid", DOAConf.repoDoid); - return doipConfig.toString(); - } private static void deleteJelck(File file) { if (file.exists()) { @@ -331,12 +338,16 @@ public class GlobalConf { } } + public static void initDOAConfig(DOAConf doaConf) { + if (instance.doaConf == null || instance.doaConf.doipAddress == null) + resetDOAConfig(JsonUtil.toJson(doaConf)); + } + public static boolean resetMasterAddress(String val) { try { instance.masterAddress = val; KeyValueDBUtil.instance.setValue(CMTables.ConfigDB.toString(), "masterAddress", val); NetworkManager.instance.reInitNodeCenter(); - ContractRepositoryMain.start(); return true; } catch (Exception e) { LOGGER.error(e.getMessage()); @@ -437,11 +448,11 @@ public class GlobalConf { return true; } - public static boolean resetDOIPConfig(String val) { + public static boolean resetDOAConfig(String val) { try { - loadDOAConfig(val); - //TODO get prefix if needed! + loadDOAConfig(instance.doaConf, val); KeyValueDBUtil.instance.setValue(CMTables.ConfigDB.toString(), "doipConfig", val); + ContractRepositoryMain.start(); } catch (Exception e) { LOGGER.error(e.getMessage()); LOGGER.debug(ExceptionUtil.exceptionToString(e)); diff --git a/src/main/java/org/bdware/server/action/CMActions.java b/src/main/java/org/bdware/server/action/CMActions.java index 313095d..0b62505 100644 --- a/src/main/java/org/bdware/server/action/CMActions.java +++ b/src/main/java/org/bdware/server/action/CMActions.java @@ -1,9 +1,6 @@ package org.bdware.server.action; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; +import com.google.gson.*; import com.google.gson.reflect.TypeToken; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -51,6 +48,7 @@ public class CMActions implements OnHashCallback { public static FuncInvokeInfo FUNCINVOKEINFO = new FuncInvokeInfo(); // 合约调用时参数和结果 private static SecureRandom RANDOM; public ContractManagerFrameHandler handler; + public CMActions() { handler = null; } @@ -531,6 +529,43 @@ public class CMActions implements OnHashCallback { } } + @Action(async = true, userPermission = 0) + public void callBDO(JsonObject args, final ResultCallback resultCallback) { + ResultCallback wrapped = new ResultCallback() { + @Override + public void onResult(String str) { + JsonObject jo = JsonParser.parseString(str).getAsJsonObject(); + jo.remove("executionGas"); + jo.remove("extraGas"); + jo.remove("totalGas"); + jo.remove("eventRelated"); + jo.remove("needSeq"); + jo.remove("seq"); + jo.remove("isInsnLimit"); + jo.remove("size"); + try { + if (jo.has("result") && jo.get("result").isJsonPrimitive()){ + String resultStr = jo.get("result").getAsString(); + jo.add("result",JsonParser.parseString(resultStr)); + } + } catch (Exception e) { + } + resultCallback.onResult(jo); + } + }; + // String sequencing = args.get("sequencing").getAsString(); + if (args.has("shortId")) + args.add("contractID", args.get("shortId")); + if (!args.has("useP2P") || !args.get("useP2P").getAsBoolean()) { + executeContractInternal(args, wrapped, this); + } else { + wrapped.onResult( + JsonUtil.toJson( + new ContractResult( + ContractResult.Status.Error, new JsonPrimitive("noResult")))); + } + } + // 节点管理者 @Action(userPermission = 1L << 19) public void listAllContractProcess(JsonObject args, ResultCallback resultCallback) { @@ -673,7 +708,6 @@ public class CMActions implements OnHashCallback { } c.setScript(script); c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); ret.put(fileName, manager.startContract(c)); if (args.has("dumpPeriod")) { @@ -706,6 +740,7 @@ public class CMActions implements OnHashCallback { @Action(userPermission = 1L << 26, async = true) public void startContractByYPK(JsonObject args, ResultCallback resultCallback) { LOGGER.info("[CMActions] startContractByYPK : "); + long start = System.currentTimeMillis(); Map ret = new HashMap<>(); Contract c = new Contract(); @@ -723,13 +758,10 @@ public class CMActions implements OnHashCallback { } if (args.has("publicKey")) { c.setOwner(args.get("publicKey").getAsString()); - c.setSignature(args.get("signature").getAsString()); } else if (args.has("owner")) { c.setOwner(args.get("owner").getAsString()); - c.setSignature(args.get("signature").getAsString()); } else { c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); } if (args.has("createParam")) { c.setCreateParam(args.get("createParam")); @@ -801,13 +833,10 @@ public class CMActions implements OnHashCallback { LOGGER.info("+++++++++++++++" + args.get("script").getAsString()); if (args.has("publicKey")) { c.setOwner(args.get("publicKey").getAsString()); - c.setSignature(args.get("signature").getAsString()); } else if (args.has("owner")) { c.setOwner(args.get("owner").getAsString()); - c.setSignature(args.get("signature").getAsString()); } else { c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); } if (args.has("createParam")) { c.setCreateParam(args.get("createParam")); @@ -910,13 +939,10 @@ public class CMActions implements OnHashCallback { LOGGER.debug("+++++++++++++++" + args.get("script").getAsString()); if (args.has("publicKey")) { c.setOwner(args.get("publicKey").getAsString()); - c.setSignature(args.get("signature").getAsString()); } else if (args.has("owner")) { c.setOwner(args.get("owner").getAsString()); - c.setSignature(args.get("signature").getAsString()); } else { c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); } c.setDebug(true); System.out.println(c.isDebug()); diff --git a/src/main/java/org/bdware/server/action/ManagerActions.java b/src/main/java/org/bdware/server/action/ManagerActions.java index 992227e..9be40d2 100644 --- a/src/main/java/org/bdware/server/action/ManagerActions.java +++ b/src/main/java/org/bdware/server/action/ManagerActions.java @@ -76,7 +76,7 @@ public class ManagerActions { data = status = GlobalConf.resetDataChain(val); break; case "doipConfig": - data = status = GlobalConf.resetDOIPConfig(val); + data = status = GlobalConf.resetDOAConfig(val); break; case "nodeCenter": data = status = GlobalConf.resetNodeCenter(val); @@ -114,7 +114,7 @@ public class ManagerActions { data.put("licence", GlobalConf.instance.licence); data.put("expireTime", new Date(GlobalConf.instance.expireTime) + ""); data.put("nodeName", GlobalConf.instance.name); - data.put("doipConfig", GlobalConf.getDOAConfig()); + data.put("doipConfig", GlobalConf.instance.doaConf); ReplyUtil.replyWithStatus(resultCallback, "onLoadConfig", true, data); } @@ -143,8 +143,7 @@ public class ManagerActions { data.put("licence", GlobalConf.instance.licence); data.put("nodeName", GlobalConf.instance.name); data.put("ipPort", GlobalConf.instance.ipPort); - data.put("doipConfig", GlobalConf.getDOAConfig()); - data.put("isLAN", String.valueOf(GlobalConf.isLAN())); + data.put("doipConfig", JsonUtil.toJson(GlobalConf.instance.doaConf)); data.put("peerID", GlobalConf.instance.peerID); data.put("bdledger", GlobalConf.instance.datachainConf.replace("\n", " ")); data.put("clusterConnected", String.valueOf(NetworkManager.instance.isConnectedToNodeCenter())); @@ -192,7 +191,7 @@ public class ManagerActions { @Action(userPermission = 1 << 10) public void changeDOIPConfig(JsonObject args, ResultCallback resultCallback) { String val = args.get("data").getAsString(); - ReplyUtil.replyWithStatus(resultCallback, "onChangeDOIPConfig", true, GlobalConf.resetDOIPConfig(val)); + ReplyUtil.replyWithStatus(resultCallback, "onChangeDOIPConfig", true, GlobalConf.resetDOAConfig(val)); } @Action(userPermission = 1 << 10) diff --git a/src/main/java/org/bdware/server/action/p2p/MasterServerTransferAction.java b/src/main/java/org/bdware/server/action/p2p/MasterServerTransferAction.java index 5562f26..f8cdfdf 100644 --- a/src/main/java/org/bdware/server/action/p2p/MasterServerTransferAction.java +++ b/src/main/java/org/bdware/server/action/p2p/MasterServerTransferAction.java @@ -88,8 +88,6 @@ public class MasterServerTransferAction { c.setID(contractID); c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); - try { File temp = new File(path); if (temp.isFile() && temp.exists()) c.setScript(temp.getAbsolutePath()); @@ -119,7 +117,6 @@ public class MasterServerTransferAction { c.setID(contractID); c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); c.setScript(script); return CMActions.manager.startContract(c); diff --git a/src/main/java/org/bdware/server/action/p2p/_UNUSED_ExecutionAction.java b/src/main/java/org/bdware/server/action/p2p/_UNUSED_ExecutionAction.java index cc2d6f9..1e8e38b 100644 --- a/src/main/java/org/bdware/server/action/p2p/_UNUSED_ExecutionAction.java +++ b/src/main/java/org/bdware/server/action/p2p/_UNUSED_ExecutionAction.java @@ -59,7 +59,6 @@ public class _UNUSED_ExecutionAction implements OnHashCallback { // contractID not hash c.setID(contractID); c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr()); - c.doSignature(GlobalConf.instance.keyPair); // c.setConsensusType(sequencing); // c.setNetworkType(network); if (content != null && content.startsWith("/")) { diff --git a/src/main/java/org/bdware/server/doip/BCOManager.java b/src/main/java/org/bdware/server/doip/BCOManager.java new file mode 100644 index 0000000..fc72be7 --- /dev/null +++ b/src/main/java/org/bdware/server/doip/BCOManager.java @@ -0,0 +1,130 @@ +package org.bdware.server.doip; + +import com.google.gson.Gson; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.bdosclient.CodeRepoClient; +import org.bdware.bdosclient.bean.UploadingStatus; +import org.bdware.bdosclient.bean.YPKInfo; +import org.bdware.doip.audit.EndpointConfig; +import org.bdware.doip.audit.client.AuditIrpClient; +import org.bdware.doip.audit.writer.AuditType; +import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.doip.endpoint.client.DoipMessageCallback; +import org.bdware.irp.client.IrpClient; +import org.bdware.sc.db.CMTables; +import org.bdware.sc.db.KeyValueDBUtil; +import org.bdware.server.GlobalConf; +import org.zz.gmhelper.SM2KeyPair; + +import java.io.File; +import java.util.concurrent.atomic.AtomicInteger; + +public class BCOManager { + CodeRepoClient client; + File bcodir; + IrpClient irpClient; + static Logger LOGGER = LogManager.getLogger(BCOManager.class); + + public BCOManager(String doid, File bcoDir, IrpClient irpClient, SM2KeyPair keyPair) { + String codeRepoDoid = CodeRepoClient.getDefaultCodeRepo(doid); + this.irpClient = irpClient; + this.bcodir = bcoDir; + client = new CodeRepoClient(codeRepoDoid, irpClient, keyPair); + } + public String download(String bCoId) { + YPKInfo ypkInfo = new YPKInfo(); + client.retrieveBCO(bCoId, new DoipMessageCallback() { + @Override + public void onResult(DoipMessage doipMessage) { + String body = doipMessage.body.getDataAsJsonString(); + YPKInfo parsed = new Gson().fromJson(body, YPKInfo.class); + if (parsed != null && parsed.md5 != null && parsed.status == UploadingStatus.Finished) { + ypkInfo.copyFrom(parsed); + } + synchronized (ypkInfo) { + ypkInfo.notify(); + } + } + }); + synchronized (ypkInfo) { + try { + if (ypkInfo.status == null) + ypkInfo.wait(1000L); + } catch (Exception e) { + } + } + if (ypkInfo.status == UploadingStatus.Finished) { + File target = getYpkFile(ypkInfo); + if (target.exists() && (client.calFileMd5(target.getAbsolutePath()) + ".ypk").equals(target.getName())) + return target.getAbsolutePath(); + DownloadProgressChecker checker = new DownloadProgressChecker(); + client.downloadYPK(bCoId, checker, target); + checker.waitForResult(30000); + if (checker.isSuccess) + return target.getAbsolutePath(); + } + return null; + } + + static class DownloadProgressChecker implements CodeRepoClient.ProgressCallback { + boolean finished = false; + boolean isSuccess = false; + + @Override + public void onStart(String s) { + + } + + @Override + public void onProgress(String s, int i, int i1) { + LOGGER.info(s + " " + i + " /" + i1); + } + + @Override + public void onFinish(String s) { + finished = true; + isSuccess = true; + synchronized (this) { + this.notify(); + } + } + + @Override + public void onError(String s, DoipMessage doipMessage) { + finished = true; + isSuccess = false; + synchronized (this) { + this.notify(); + } + + } + + public void waitForResult(long timeout) { + synchronized (this) { + if (!this.finished) { + try { + this.wait(timeout); + } catch (InterruptedException e) { + } + } + } + } + } + + private File getYpkFile(YPKInfo ypkInfo) { + File f = new File(bcodir, ypkInfo.ypkName); + if (ypkInfo.version != null) + f = new File(f, ypkInfo.version); + f = new File(f, ypkInfo.md5 + ".ypk"); + return f; + } + + private static AuditIrpClient initIrpClient() { + EndpointConfig config = new EndpointConfig(); + config.routerURI = GlobalConf.instance.doaConf.lhsAddress; + config.auditType = AuditType.None; + AuditIrpClient irpClient = new AuditIrpClient(GlobalConf.instance.doaConf.repoDoid, config); + return irpClient; + } +} diff --git a/src/main/java/org/bdware/server/doip/ContractRepositoryHandler.java b/src/main/java/org/bdware/server/doip/ContractRepositoryHandler.java index be3d292..37b4b4f 100644 --- a/src/main/java/org/bdware/server/doip/ContractRepositoryHandler.java +++ b/src/main/java/org/bdware/server/doip/ContractRepositoryHandler.java @@ -5,32 +5,61 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.netty.channel.ChannelHandler; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.doip.audit.EndpointConfig; +import org.bdware.doip.audit.client.AuditIrpClient; +import org.bdware.doip.audit.server.DefaultRepoHandlerInjector; import org.bdware.doip.codec.digitalObject.DigitalObject; import org.bdware.doip.codec.digitalObject.DoType; import org.bdware.doip.codec.digitalObject.Element; import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.doip.codec.doipMessage.DoipMessageFactory; import org.bdware.doip.codec.doipMessage.DoipResponseCode; import org.bdware.doip.codec.operations.BasicOperations; import org.bdware.doip.endpoint.server.DoipServiceInfo; import org.bdware.doip.endpoint.server.Op; import org.bdware.doip.endpoint.server.RepositoryHandlerBase; import org.bdware.sc.ContractClient; +import org.bdware.sc.ContractMeta; +import org.bdware.sc.ContractStatusEnum; +import org.bdware.sc.bean.Contract; +import org.bdware.sc.bean.ContractExecType; import org.bdware.sc.bean.ContractRequest; import org.bdware.sc.bean.FunctionDesp; import org.bdware.sc.conn.ResultCallback; +import org.bdware.sc.db.CMTables; +import org.bdware.sc.db.KeyValueDBUtil; import org.bdware.sc.util.JsonUtil; +import org.bdware.server.GlobalConf; import org.bdware.server.action.CMActions; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; import java.util.ArrayList; import java.util.List; @ChannelHandler.Sharable -public class ContractRepositoryHandler extends RepositoryHandlerBase { +public class ContractRepositoryHandler extends RepositoryHandlerBase implements DefaultRepoHandlerInjector { + BCOManager bcoManager; + static Logger LOGGER = LogManager.getLogger(ContractRepositoryHandler.class); public ContractRepositoryHandler(DoipServiceInfo info) { super(info); + GlobalConf.DOAConf doaConf = GlobalConf.instance.doaConf; + String bcoDir = GlobalConf.instance.bcoDir; + EndpointConfig config = new EndpointConfig(); + config.routerURI = doaConf.lhsAddress; + AuditIrpClient client = new AuditIrpClient(config); + bcoManager = new BCOManager(doaConf.repoDoid, new File(bcoDir), client, GlobalConf.instance.keyPair); } + CMActions cmActions = new CMActions(); + + @Override public DoipMessage handleHello(DoipMessage doipMessage) { return replyDoipServiceInfo(doipMessage); @@ -38,6 +67,9 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { @Override public DoipMessage handleListOps(DoipMessage doipMessage) { + if (!GlobalConf.instance.doaConf.repoDoid.equals(doipMessage.header.parameters.id)) { + return replyStringWithStatus(doipMessage, "unsupported doid:" + doipMessage.header.parameters.id, DoipResponseCode.DoNotFound); + } JsonArray ops = new JsonArray(); ops.add(BasicOperations.Hello.getName()); ops.add("call"); @@ -46,7 +78,55 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { @Override public DoipMessage handleCreate(DoipMessage doipMessage) { - return replyStringWithStatus(doipMessage, "not supported yet", DoipResponseCode.Declined); + if (!GlobalConf.instance.doaConf.repoDoid.equals(doipMessage.header.parameters.id)) { + return replyStringWithStatus(doipMessage, "unsupported doid:" + doipMessage.header.parameters.id, DoipResponseCode.DoNotFound); + } + //TODD 验证签名。完事后进入 + if (doipMessage.credential != null && doipMessage.credential.getSigner() != null) { + String permissions = KeyValueDBUtil.instance.getValue(CMTables.NodeRole.toString(), doipMessage.credential.getSigner()); + if (!permissions.contains("ContractInstanceManager")) { + return replyStringWithStatus(doipMessage, "permission denied, role:" + permissions, DoipResponseCode.Declined); + } + } + DigitalObject digitalObject = null; + try { + digitalObject = doipMessage.body.getDataAsDigitalObject(); + digitalObject.attributes.remove("verifiedPubKey"); + } catch (Exception e) { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + return replyStringWithStatus(doipMessage, "exception:" + new String(bo.toByteArray()), DoipResponseCode.Invalid); + } + DoipMessage[] content = new DoipMessage[1]; + digitalObject.attributes.addProperty("verifiedPubKey", doipMessage.credential.getSigner()); + String path = null; + if (digitalObject.attributes.has("bCoId")) + path = bcoManager.download(digitalObject.attributes.get("bCoId").getAsString()); + + if (path == null) { + return replyStringWithStatus(doipMessage, "exception, failed to locate bCoId:" + digitalObject.attributes.get("bCoId").getAsString(), DoipResponseCode.Invalid); + } + digitalObject.attributes.addProperty("path", path); + Contract c = new Contract(); + if (digitalObject.attributes.has("contractExecType")) + c.setType(ContractExecType.valueOf(digitalObject.attributes.get("contractExecType").getAsString())); + else c.setType(ContractExecType.Sole); + c.setScript(path); + c.setOwner(doipMessage.credential.getSigner()); + if (digitalObject.attributes.has("createParam")) { + c.setCreateParam(digitalObject.attributes.get("createParam")); + } + SM2KeyPair sm2Key; + if (digitalObject.attributes.has("sm2KeyPair")) + sm2Key = SM2KeyPair.fromJson(digitalObject.attributes.get("sm2KeyPair").getAsJsonObject().toString()); + else sm2Key = SM2Util.generateSM2KeyPair(); + String contractID = String.valueOf(sm2Key.getPublicKeyStr().hashCode()); + c.setID(contractID); // contractID是根据hash算出来的 + c.setKey(sm2Key.getPrivateKeyStr()); + c.setPublicKey(sm2Key.getPublicKeyStr()); + String result = CMActions.manager.startContract(c); + //Please note startContractByYPK is invoked in sync mode method. + return replyStringWithStatus(doipMessage, result, DoipResponseCode.Success); } @Override @@ -56,7 +136,20 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { @Override public DoipMessage handleDelete(DoipMessage doipMessage) { - return replyStringWithStatus(doipMessage, "not supported yet", DoipResponseCode.Declined); + String id = doipMessage.header.parameters.id; + //TODO judge whethere the do exists + ContractMeta meta = CMActions.manager.statusRecorder.getContractMeta(id); + if (meta == null) { + return replyStringWithStatus(doipMessage, "can't locate do", DoipResponseCode.DoNotFound); + } + if (meta.getStatus() == ContractStatusEnum.KILLED) { + return replyStringWithStatus(doipMessage, "already deleted!", DoipResponseCode.Declined); + } + DoipMessage[] content = new DoipMessage[1]; + JsonObject jo = new JsonObject(); + jo.addProperty("action", "killContractProcess"); + String result = CMActions.manager.stopContract(meta.getID()); + return replyStringWithStatus(doipMessage, result, DoipResponseCode.Success); } @Override @@ -69,13 +162,11 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { if (client == null) { String doid = doipMessage.header.parameters.id; int off = doid.lastIndexOf("/"); - if (off > 0) - doid = doid.substring(off + 1); + if (off > 0) doid = doid.substring(off + 1); client = CMActions.manager.getContractClientByDoi(doid); } if (client == null) { - return replyStringWithStatus( - doipMessage, "Contract instance not exist!", DoipResponseCode.DoNotFound); + return replyStringWithStatus(doipMessage, "Contract instance not exist!", DoipResponseCode.DoNotFound); } byte[] data = doipMessage.body.getEncodedData(); @@ -137,8 +228,7 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { public DoipMessage handleCall(DoipMessage doipMessage) { ContractClient cc = CMActions.manager.getContractClientByDoi(doipMessage.header.parameters.id); if (cc == null) - return replyStringWithStatus( - doipMessage, "Contract instance not exist!", DoipResponseCode.DoNotFound); + return replyStringWithStatus(doipMessage, "Contract instance not exist!", DoipResponseCode.DoNotFound); // todo transform doipMessage to args JsonObject args = doipMessage.header.parameters.attributes; ContractRequest cr = new ContractRequest(); @@ -146,18 +236,15 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { cr.setContractID(cc.getContractID()); cr.setContractDOI(doipMessage.header.parameters.id); - if (args.has("withDynamicAnalysis")) - cr.withDynamicAnalysis = args.get("withDynamicAnalysis").getAsBoolean(); + if (args.has("withDynamicAnalysis")) cr.withDynamicAnalysis = args.get("withDynamicAnalysis").getAsBoolean(); if (args.has("withEvaluatesAnalysis")) cr.withEvaluatesAnalysis = args.get("withEvaluatesAnalysis").getAsBoolean(); if (args.get("elementID") == null) - return replyStringWithStatus( - doipMessage, "missing elementID", DoipResponseCode.Invalid); + return replyStringWithStatus(doipMessage, "missing elementID", DoipResponseCode.Invalid); cr.setAction(args.get("elementID").getAsString()); - if (doipMessage.body.getEncodedData() != null) - cr.setArg(new String(doipMessage.body.getEncodedData())); + if (doipMessage.body.getEncodedData() != null) cr.setArg(new String(doipMessage.body.getEncodedData())); if (doipMessage.credential != null && doipMessage.credential.getSigner() != null) cr.setRequesterDOI(doipMessage.credential.getSigner()); @@ -179,4 +266,33 @@ public class ContractRepositoryHandler extends RepositoryHandlerBase { } + @Override + public void injectCreate(DoipMessage request, DoipMessageFactory.DoipMessageBuilder builder) { + builder.setDoipMessage(handleCreate(request)); + } + + @Override + public void injectHello(DoipMessage request, DoipMessageFactory.DoipMessageBuilder builder) { + builder.setDoipMessage(handleHello(request)); + } + + @Override + public void injectListOps(DoipMessage doipMessage, DoipMessageFactory.DoipMessageBuilder builder) { + builder.setDoipMessage(handleListOps(doipMessage)); + } + + @Override + public void injectUpdate(DoipMessage request, DoipMessageFactory.DoipMessageBuilder builder) { + // use default behavior + } + + @Override + public void injectRetrieve(DoipMessage doipMessage, DoipMessageFactory.DoipMessageBuilder builder) { + builder.setDoipMessage(handleRetrieve(doipMessage)); + } + + @Override + public void injectDelete(DoipMessage doipMessage, DoipMessageFactory.DoipMessageBuilder builder) { + builder.setDoipMessage(handleDelete(doipMessage)); + } } diff --git a/src/main/java/org/bdware/server/doip/ContractRepositoryMain.java b/src/main/java/org/bdware/server/doip/ContractRepositoryMain.java index 3e64044..a6555b4 100644 --- a/src/main/java/org/bdware/server/doip/ContractRepositoryMain.java +++ b/src/main/java/org/bdware/server/doip/ContractRepositoryMain.java @@ -2,10 +2,11 @@ package org.bdware.server.doip; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.bdware.doip.audit.EndpointConfig; +import org.bdware.doip.audit.server.AuditDoipServer; +import org.bdware.doip.audit.writer.AuditType; import org.bdware.doip.endpoint.server.DoipListenerConfig; -import org.bdware.doip.endpoint.server.DoipServerImpl; import org.bdware.doip.endpoint.server.DoipServiceInfo; -import org.bdware.server.DOAConf; import org.bdware.server.GlobalConf; import java.util.ArrayList; @@ -13,32 +14,35 @@ import java.util.List; public class ContractRepositoryMain { private static final Logger LOGGER = LogManager.getLogger(ContractRepositoryMain.class); - static DoipServerImpl currentServer; + static AuditDoipServer currentServer; + static final String repoType = "BDRepo"; public static void start() { try { - String[] ipAndPort = GlobalConf.instance.masterAddress.split(":"); - String url = String.format("tcp://%s:%d", ipAndPort[0], Integer.valueOf(ipAndPort[1]) + 1); - String doid = DOAConf.repoDoid; + String url = GlobalConf.instance.doaConf.doipAddress; LOGGER.info("DOIPServer start:" + url); - if (url == null || doid == null) { - LOGGER.warn("missing args, failed to start! url:" + url + " doid:" + doid); + if (url == null || GlobalConf.instance.doaConf.repoDoid.isEmpty()) { + LOGGER.warn("missing args, failed to start! url:" + url + " doid:" + GlobalConf.instance.doaConf.repoDoid); return; } if (currentServer != null) { currentServer.stop(); } - List infos = new ArrayList<>(); infos.add(new DoipListenerConfig(url, "2.1")); - DoipServiceInfo info = new DoipServiceInfo(doid, "bdware.trust/Admin", "ContractRepo", infos); - currentServer = new DoipServerImpl(info); + DoipServiceInfo info = new DoipServiceInfo(GlobalConf.instance.doaConf.repoDoid, GlobalConf.instance.keyPair.getPublicKeyStr(), repoType, infos); + EndpointConfig config = new EndpointConfig(); + config.publicKey = GlobalConf.instance.keyPair.getPublicKeyStr(); + config.privateKey = GlobalConf.instance.keyPair.getPrivateKeyStr(); + config.auditType = AuditType.None; + config.routerURI = GlobalConf.instance.doaConf.lhsAddress; + config.repoName = GlobalConf.instance.doaConf.repoName; + currentServer = new AuditDoipServer(config); currentServer.setRepositoryHandler(new ContractRepositoryHandler(info)); currentServer.start(); } catch (Exception e) { e.printStackTrace(); LOGGER.warn("load doip config exception!"); } - } } diff --git a/src/main/java/org/bdware/server/doip/ContractRepositoryServer.java b/src/main/java/org/bdware/server/doip/ContractRepositoryServer.java deleted file mode 100644 index 100e8b1..0000000 --- a/src/main/java/org/bdware/server/doip/ContractRepositoryServer.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.bdware.server.doip; - -public class ContractRepositoryServer { - -} diff --git a/src/main/java/org/bdware/server/http/CMHttpHandler.java b/src/main/java/org/bdware/server/http/CMHttpHandler.java index ebe6bfb..0dc346b 100644 --- a/src/main/java/org/bdware/server/http/CMHttpHandler.java +++ b/src/main/java/org/bdware/server/http/CMHttpHandler.java @@ -185,7 +185,7 @@ public class CMHttpHandler extends SimpleChannelInboundHandler { LOGGER.info("[OOOOOOOOption] received!"); } - @URIPath({"/SCIDE/CMManager", "/SCIDE/SCManager"}) + @URIPath({"/SCIDE/CMManager", "/SCIDE/SCManager", "/BDO"}) public void handleHttpGet(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { JsonObject transformedParam = ArgParser.parseGetAndVerify(msg, new ArgParser.VerifiedCallback() { @Override @@ -214,7 +214,7 @@ public class CMHttpHandler extends SimpleChannelInboundHandler { @URIPath( method = HttpMethod.POST, - value = {"/SCIDE/CMManager", "/SCIDE/SCManager"}) + value = {"/SCIDE/CMManager", "/SCIDE/SCManager", "/BDO"}) public void handleHttpPost(ChannelHandlerContext ctx, FullHttpRequest msg) throws UnsupportedEncodingException { // http请求中规定签名必须是最后一个且公钥名必须为pubKey,否则验签失败 diff --git a/src/test/java/org/bdware/server/DOIPTest.java b/src/test/java/org/bdware/server/DOIPTest.java deleted file mode 100644 index e2b079a..0000000 --- a/src/test/java/org/bdware/server/DOIPTest.java +++ /dev/null @@ -1,63 +0,0 @@ -//package org.bdware.server; -// -//import org.bdware.doip.core.doipMessage.DoipMessage; -//import org.bdware.doip.core.doipMessage.DoipMessageFactory; -//import org.bdware.doip.core.model.operations.BasicOperations; -//import org.bdware.doip.endpoint.doipClient.DoipClientImpl; -//import org.bdware.doip.endpoint.doipClient.DoipMessageCallback; -//import org.junit.Before; -//import org.junit.Test; -// -//import java.nio.charset.StandardCharsets; -//import java.util.ArrayList; -//import java.util.List; -// -//public class DOIPTest { -// public static String repoID = "86.5000.470/doip.localContractRepo"; -// -// -// @Before -// public void init() { -// } -// -// @Test -// public void registryTempOD() { -// -// } -// -// @Test -// public void retrieve() { -// try { -// DoipClientImpl doipClient = new DoipClientImpl(); -// doipClient.connect("tcp://127.0.0.1:18002"); -// //86.5000.470/do.Yie0yPsjt4_bdw -// List ret = new ArrayList<>(); -// DoipMessage msg = (new DoipMessageFactory.DoipMessageBuilder()).createRequest("86.5000.470/Counter", BasicOperations.Retrieve.getName()) -// .setBody("{\"operation\":\"count\",\"arg\":\"\"}".getBytes(StandardCharsets.UTF_8)).create(); -// doipClient.sendMessage(msg, new DoipMessageCallback() { -// @Override -// public void onResult(DoipMessage doipMessage) { -// ret.add(doipMessage); -// synchronized (ret) { -// ret.notify(); -// } -// } -// }); -// synchronized (ret) { -// ret.wait(5000); -// } -// DoipMessage result = null; -// if (ret.size() > 0) -// result = ret.get(0); -// System.out.println(result.body.getDataAsJsonString()); -// // GlobalIrpClient.getGlobalClient().reRegister(doHandleRecord); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// -// @Test -// public void call() { -// -// } -//} diff --git a/src/test/java/org/bdware/server/DoipClientTest.java b/src/test/java/org/bdware/server/DoipClientTest.java new file mode 100644 index 0000000..16dc4df --- /dev/null +++ b/src/test/java/org/bdware/server/DoipClientTest.java @@ -0,0 +1,37 @@ +package org.bdware.server; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.doip.endpoint.client.ClientConfig; +import org.bdware.doip.endpoint.client.DoipClientImpl; +import org.bdware.doip.endpoint.client.DoipMessageCallback; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicInteger; + +public class DoipClientTest { + static Logger LOGGER = LogManager.getLogger(DoipClientTest.class); + private DoipClientImpl client; + + @Before + public void init() { + this.client = new DoipClientImpl(); + client.connect(ClientConfig.fromUrl("tcp://127.0.0.1:18002")); + } + + @Test + public void test() { + AtomicInteger i = new AtomicInteger(0); + client.hello("abc", new DoipMessageCallback() { + @Override + public void onResult(DoipMessage msg) { + i.incrementAndGet(); + LOGGER.info(msg); + } + }); + for (; i.get() == 0; ) Thread.yield(); + + } +} diff --git a/src/test/java/org/bdware/server/doip/BCOManagerTest.java b/src/test/java/org/bdware/server/doip/BCOManagerTest.java new file mode 100644 index 0000000..1f024b2 --- /dev/null +++ b/src/test/java/org/bdware/server/doip/BCOManagerTest.java @@ -0,0 +1,36 @@ +package org.bdware.server.doip; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.doip.audit.EndpointConfig; +import org.bdware.doip.audit.client.AuditIrpClient; +import org.junit.Before; +import org.junit.Test; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +import java.io.File; + +public class BCOManagerTest { + private BCOManager bcoManager; + static final Logger LOGGER = LogManager.getLogger(BCOManagerTest.class); + + @Before + public void init() { + EndpointConfig config = new EndpointConfig(); + config.routerURI = "tcp://127.0.0.1:21041"; + AuditIrpClient client = new AuditIrpClient(config); + SM2KeyPair key = SM2Util.generateSM2KeyPair(); + + // config.privateKey = key.getPrivateKeyStr(); + // config.publicKey = key.getPublicKeyStr(); + + this.bcoManager = new BCOManager("bdtest/CodeRepository", new File("./BDWareProjectDir/bco"), client, key); + } + + @Test + public void downloadTest() { + String result = bcoManager.download("bdtest/CodeRepository/broadcastwithoutroute/0.0.1"); + LOGGER.info(result); + } +}