package foundation.icall; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import foundation.action.ActionContext; import foundation.action.SingletonActionProvider; import foundation.action.WorkStep; import foundation.dao.DataPackage; import foundation.dao.DataReader; import foundation.dao.DataWriter; import foundation.dao.IDataLetter; import foundation.data.entity.Entity; import foundation.data.object.DataObject; import foundation.handler.DataPool; import foundation.handler.ResultPool; import foundation.icall.callin.BodyReader; import foundation.icall.callout.HttpServerSource; import foundation.icall.callout.RemoteSourceBucket; import foundation.icall.log.LogRecord; import foundation.io.object.DownloadAction; import foundation.io.object.DownloadWriter; import foundation.json.JObjectReader; import foundation.json.JType; import foundation.route.Operation; import foundation.util.Util; public class ICallCenter extends SingletonActionProvider { protected static Logger logger; private static ICallCenter instance; private static ICallBucket icallBucket; static { logger = LogManager.getLogger(ICallCenter.class); } private ICallCenter() { icallBucket = ICallBucket.getInstance(); } public static synchronized ICallCenter getInstance() { if (instance == null) { instance = new ICallCenter(); } return instance; } @Override protected void publishMethod() { //1. 执行接口 addMethod("callRemote"); //2. inBound addMethod("callIn"); //3. call remote addMethod("callRemoteServer"); //4. remote database addMethod("callRemoteDB"); //5. 执行 Echo 接口 addMethod("echo"); //6. 获取接口描述 addMethod("getMeta"); //7. 获取接口日志分类树 addMethod("getLogCategory"); //8. 获取某个具体接口的日志列表 addMethod("getLogList"); //9. 获取某个具体请求的Request日志 addMethod("getRequestFile"); //10. 获取某个具体请求的Response日志 addMethod("getResponseFile"); //11. 重新加载接口参数 addMethod("reloadInterfaceSource"); } public void callRemote(ActionContext context, ICall iCall) throws Exception { ICallDirection direction = iCall.getType(); if (ICallDirection.RemoteServer == direction) { callRemoteServer(context, iCall); } else if (ICallDirection.RemoteDB == direction) { callRemoteDB(context, iCall); } } public void callIn(ActionContext context, ICall iCall) throws Exception { DataWriter dataWriter = context.getDataWriter(); InboundResult result = new InboundResult(iCall); //1. get data package String dataName = iCall.getDataName(); DataPackage dataPackage = DataPackage.getInstance(dataName); if (dataPackage == null) { throw new Exception("call in bound error, invalid data name: " + dataName); } //2. get request data DataReader requestReader = context.getDataReader(); if (!requestReader.has(IDataLetter.Data)) { dataWriter.reportOneError("DataNotExists", "data not exists in request"); logger.error("absent data interface call, skip"); return; } JObjectReader dataReader = requestReader.getReader(IDataLetter.Data, JType.Object); //3. 加载DataPackage BodyReader bodyReader = new BodyReader(dataReader, dataPackage, iCall.getMappings()); int received = bodyReader.parse(); result.setReceived(received); //4. 保存数据到数据库 if (!dataPackage.isEmpty()) { int saved = dataPackage.saveOneDataToPersist(); result.setSaved(saved); } //5. result dataWriter.addValue(result); } private void callRemoteServer(ActionContext context, ICall iCall) throws Exception { DataWriter dataWriter = context.getDataWriter(); OutboundResult result = new OutboundResult(iCall); //1. get data package DataPackage dataPackage = context.getDataPackage(); if (dataPackage != null) { DataPackage host = dataPackage.getHost(); if (host != null) { host.setMasterId(dataPackage.getHostID()); host.loadOneDataFromFile(); dataPackage = host; } } //2. 调用 远端接口 HttpServerSource source = iCall.remoteSource(); source.login(context, iCall); try { iCall.sendRemoteServerCall(context, result); } finally { source.logout(context, iCall); } //4. result dataWriter.addValue(result); } private void callRemoteDB(ActionContext context, ICall iCall) throws Exception { DataWriter dataWriter = context.getDataWriter(); OutboundResult result = new OutboundResult(iCall); LogRecord record = new LogRecord(iCall); result.setRecord(record); //1. 运行远程SQL iCall.sendRemoteDBCall(context, result); //2. result if (dataWriter != null) { dataWriter.addValue(result); } } public void echo(ActionContext context, ICall iCall) throws Exception { DataWriter dataWriter = context.getDataWriter(); InboundResult result = new InboundResult(iCall); //1. try get data package String dataName = iCall.getDataName(); DataPackage dataPackage = DataPackage.getInstance(dataName); //2. try get request data DataReader requestReader = context.getDataReader(); JObjectReader dataReader = requestReader.getReader(IDataLetter.Data, JType.Object); //3. 加载DataPackage BodyReader bodyReader = new BodyReader(dataReader, dataPackage, iCall.getMappings()); int received = bodyReader.parse(); result.setReceived(received); //4. 保存数据到数据库 result.setResponseBody(requestReader.getBody()); //5. result dataWriter.addValue(result); } public void getMeta(ActionContext context, ICall iCall) throws Exception { DataWriter dataWriter = context.getDataWriter(); ICallMeta meta = iCall.getMeta(); dataWriter.addValue(meta); } public void getRequestFile(ActionContext context, ICall iCall) throws Exception { DataWriter dataWriter = context.getDataWriter(); DataReader dataReader = context.getDataReader(); //1. 从请求中得到日志ID String id = dataReader.getString("id"); if (Util.isEmpty(id)) { logger.error("request has no id"); return; } //2. 获取数据文件 DataObject dataObject = DataObject.getInstance("sys_interface_log"); Entity entity = dataObject.getTableEntity(id); if (entity == null) { logger.error("log record not exists"); return; } String path = entity.getString("request_content"); File file = new File(path); if (!file.exists()) { logger.error("file not exists: {}", file); return; } //3. 返回文件流 DownloadWriter downloadWriter = new DownloadWriter(dataWriter); downloadWriter.write(file, "requestbody", DownloadAction.ASTexT); } public void getResponseFile(ActionContext context, String method) throws Exception { DataWriter dataWriter = context.getDataWriter(); DataReader dataReader = context.getDataReader(); //1. 从请求中得到日志ID String id = dataReader.getString("id"); if (Util.isEmpty(id)) { logger.error("request has no id"); return; } //2. 获取数据文件 DataObject dataObject = DataObject.getInstance("sys_interface_log"); Entity entity = dataObject.getTableEntity(id); if (entity == null) { logger.error("log record not exists"); return; } String path = entity.getString("return_content"); File file = new File(path); if (!file.exists()) { logger.error("file not exists: {}", file); return; } //3. 返回文件流 DownloadWriter downloadWriter = new DownloadWriter(dataWriter); downloadWriter.write(file, "responsebody", DownloadAction.ASTexT); } @Override public void exec(ActionContext context, String methodName) throws Exception { String iCallName = context.getStepParam(); if (Util.isEmpty(iCallName)) { DataReader dataReader = context.getDataReader(); iCallName = dataReader.getString("icall"); } ICall iCall = icallBucket.getOne(iCallName); Method method = getMethod(methodName); try { method.invoke(this, context, iCall); } catch (InvocationTargetException e) { e.printStackTrace(); Throwable throwable = e.getTargetException(); if (throwable == null) { throw e; } else { throw (Exception) throwable; } } catch (Exception e) { e.printStackTrace(); throw e; } } @Override protected void invokeMethod(Method method, DataPool dataPool, ResultPool resultPool) throws Exception { //1. 创建 reader 和 writer Operation operation = dataPool.getOperation(); DataReader dataReader = new DataReader(operation, dataPool); DataWriter dataWriter = new DataWriter(resultPool, dataReader.getDomain()); resultPool.setLetterWriter(dataWriter); //2. 创建 ICall, 请求样例-inbound:root/interface/call/md_org_data //2. 每次请求系统都会根据 meta 创建一个新的 iCall 和 remote source String iCallName = dataReader.getString("icall"); ICall iCall = icallBucket.getOne(iCallName); //3. 创建 action context String dataName = dataReader.getDomain().getDataName(); WorkStep step = new WorkStep(dataName, operation.getOperator()); ActionContext context = new ActionContext(dataReader, dataWriter, step); //4. 调用方法 try { method.invoke(this, context, iCall); } catch (InvocationTargetException e) { e.printStackTrace(); Throwable throwable = e.getTargetException(); if (throwable == null) { throw e; } else { throw (Exception) throwable; } } } @Override protected boolean validateMethodParameter(Class[] parameters) { if (parameters == null || parameters.length != 2) { return false; } Class type = parameters[0]; if (!type.isAssignableFrom(ActionContext.class)) { return false; }; type = parameters[1]; if (!type.isAssignableFrom(ICall.class)) { return false; }; return true; } public void reloadInterfaceSource(ActionContext context, ICall iCall) throws Exception { RemoteSourceBucket sourceBucket = RemoteSourceBucket.clean(); ICallLoader.loadRemoteDataBases(sourceBucket); ICallLoader.loadHttpServers(sourceBucket); } }