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);
|
}
|
}
|