Commit 02897568 authored by liang.tang's avatar liang.tang
Browse files

magic-api

parents
Pipeline #222 failed with stages
in 0 seconds
package org.ssssssss.magicapi.core.model;
import java.util.ArrayList;
import java.util.Objects;
/**
* 参数、header、path的基础信息
*
* @author mxd
*/
public class BaseDefinition {
/**
* 名
*/
private String name;
/**
* 值
*/
private Object value;
/**
* 描述
*/
private String description;
/**
* 是否必填
*/
private boolean required;
/**
* 数据类型
*/
private DataType dataType;
/**
* 类型,函数专用
*/
private String type;
/**
* 默认值
*/
private String defaultValue;
/**
* 验证类型
*/
private String validateType;
/**
* 验证说明
*/
private String error;
/**
* 验证表达式
*/
private String expression;
/**
* @Description 子集,数据类型为对象或数组时有数据
*/
private ArrayList<BaseDefinition> children;
public BaseDefinition() {
}
public BaseDefinition(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public DataType getDataType() {
return dataType == null ? DataType.String : dataType;
}
public void setDataType(DataType dataType) {
this.dataType = dataType;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public String getValidateType() {
return validateType;
}
public void setValidateType(String validateType) {
this.validateType = validateType;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public ArrayList<BaseDefinition> getChildren() {
return children;
}
public void setChildren(ArrayList<BaseDefinition> children) {
this.children = children;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof BaseDefinition)) {
return false;
}
BaseDefinition that = (BaseDefinition) o;
return required == that.required && Objects.equals(name, that.name) && Objects.equals(value, that.value) && Objects.equals(description, that.description) && dataType == that.dataType && Objects.equals(defaultValue, that.defaultValue) && Objects.equals(validateType, that.validateType) && Objects.equals(error, that.error) && Objects.equals(expression, that.expression) && Objects.equals(children, that.children);
}
@Override
public int hashCode() {
return Objects.hash(name, value, description, required, dataType, defaultValue, validateType, error, expression, children);
}
}
package org.ssssssss.magicapi.core.model;
import org.apache.commons.lang3.time.DateUtils;
import org.ssssssss.magicapi.modules.servlet.RequestModule;
import org.ssssssss.script.reflection.JavaInvoker;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import static org.ssssssss.script.reflection.JavaReflection.findInvoker;
/**
* 参数类型枚举
*
* @author mxd
*/
public enum DataType {
/**
* Object 类型
*/
Object("object"),
/**
* 数组类型
*/
Array("array"),
/**
* 任意类型
*/
Any("object"),
/**
* Boolean类型
*/
Boolean(false, findInvoker(Boolean.class, "valueOf", new Class<?>[]{String.class}), false, true, "boolean"),
/**
* String 类型
*/
String("string"),
/**
* Integer 类型
*/
Integer(true, findInvoker(BigDecimal.class, "intValue"), "number"),
/**
* Double 类型
*/
Double(true, findInvoker(BigDecimal.class, "doubleValue"), "number"),
/**
* Long 类型
*/
Long(true, findInvoker(BigDecimal.class, "longValue"), "number"),
/**
* Float 类型
*/
Float(true, findInvoker(BigDecimal.class, "floatValue"), "number"),
/**
* Byte 类型
*/
Byte(true, findInvoker(BigDecimal.class, "byteValue"), "number"),
/**
* Short类型
*/
Short(true, findInvoker(BigDecimal.class, "shortValue"), "number"),
/**
* Date类型
*/
Date(findInvoker(DataType.class, "parseDate", new Class<?>[]{String.class}), false, true, "string"),
/**
* MultipartFile 类型
*/
MultipartFile(findInvoker(RequestModule.class, "getFile", new Class<?>[]{String.class}), true, false, "file"),
/**
* List<MultipartFile> 类型
*/
MultipartFiles(findInvoker(RequestModule.class, "getFiles", new Class<?>[]{String.class}), true, false, "file");
private boolean isNumber;
private JavaInvoker<Method> invoker;
private boolean needName;
private boolean needValue;
private String javascriptType;
public static String[] DATE_PATTERNS;
DataType(boolean isNumber, JavaInvoker<Method> invoker, boolean needName, boolean needValue, String javascriptType) {
this.isNumber = isNumber;
this.invoker = invoker;
this.needName = needName;
this.needValue = needValue;
this.javascriptType = javascriptType;
}
DataType(JavaInvoker<Method> invoker, boolean needName, boolean needValue, String javascriptType) {
this(false, invoker, needName, needValue, javascriptType);
}
DataType(boolean isNumber, JavaInvoker<Method> invoker, String javascriptType) {
this(invoker, false, false, javascriptType);
this.isNumber = isNumber;
}
DataType(String javascriptType) {
this.javascriptType = javascriptType;
}
public boolean isNumber() {
return isNumber;
}
public JavaInvoker<Method> getInvoker() {
return invoker;
}
public boolean isNeedName() {
return needName;
}
public boolean isNeedValue() {
return needValue;
}
public java.lang.String getJavascriptType() {
return javascriptType;
}
public static java.util.Date parseDate(String value) throws ParseException {
return DateUtils.parseDate(value, DATE_PATTERNS);
}
}
package org.ssssssss.magicapi.core.model;
import org.ssssssss.magicapi.core.config.WebSocketSessionManager;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest;
import org.ssssssss.magicapi.utils.JsonUtils;
import org.ssssssss.script.MagicScriptDebugContext;
import org.ssssssss.script.functions.ObjectConvertExtension;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.ssssssss.magicapi.core.config.Constants.*;
import static org.ssssssss.magicapi.core.config.MessageType.BREAKPOINT;
public class DebugRequest {
private final MagicHttpServletRequest request;
private DebugRequest(MagicHttpServletRequest request) {
this.request = request;
}
public static DebugRequest create(MagicHttpServletRequest request){
return new DebugRequest(request);
}
/**
* 获得断点
*/
public List<Integer> getRequestedBreakpoints() {
String breakpoints = request.getHeader(HEADER_REQUEST_BREAKPOINTS);
if (breakpoints != null) {
return Arrays.stream(breakpoints.split(","))
.map(val -> ObjectConvertExtension.asInt(val, -1))
.filter(it -> it > 0)
.collect(Collectors.toList());
}
return Collections.emptyList();
}
/**
* 获取测试scriptId
*/
public String getRequestedScriptId() {
return request.getHeader(HEADER_REQUEST_SCRIPT_ID);
}
/**
* 获取测试clientId
*/
public String getRequestedClientId() {
return request.getHeader(HEADER_REQUEST_CLIENT_ID);
}
public MagicScriptDebugContext createMagicScriptContext(int debugTimeout){
MagicScriptDebugContext debugContext = new MagicScriptDebugContext(getRequestedBreakpoints());
String scriptId = getRequestedScriptId();
String clientId = getRequestedClientId();
debugContext.setTimeout(debugTimeout);
debugContext.setId(scriptId);
debugContext.setCallback(variables -> {
List<Map<String, Object>> varList = (List<Map<String, Object>>) variables.get("variables");
varList.stream().filter(it -> it.containsKey("value")).forEach(variable -> {
variable.put("value", JsonUtils.toJsonStringWithoutLog(variable.get("value")));
});
WebSocketSessionManager.sendByClientId(clientId, BREAKPOINT, scriptId, variables);
});
return debugContext;
}
}
package org.ssssssss.magicapi.core.model;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* 分组对象
*
* @author mxd
*/
public class Group extends Attributes<Object> {
private String id;
private String name;
private String type;
private String parentId;
private String path;
private Long createTime;
private Long updateTime;
private String createBy;
private String updateBy;
/**
* 路径变量
*/
private List<Path> paths = Collections.emptyList();
/**
* 分组选项
*/
private List<BaseDefinition> options = Collections.emptyList();
public Group(String id, String name) {
this.id = id;
this.name = name;
}
public Group() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public List<Path> getPaths() {
return paths;
}
public void setPaths(List<Path> paths) {
this.paths = paths;
}
public List<BaseDefinition> getOptions() {
return options;
}
public void setOptions(List<BaseDefinition> options) {
this.options = options;
}
public Group copy(){
Group group = new Group();
group.setId(this.id);
group.setName(this.name);
group.setType(this.type);
group.setPaths(this.paths);
group.setPath(this.path);
group.setProperties(this.properties);
group.setParentId(this.parentId);
group.setOptions(this.options);
return group;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
public Long getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Long updateTime) {
this.updateTime = updateTime;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Group group = (Group) o;
return Objects.equals(id, group.id) && Objects.equals(name, group.name) && Objects.equals(type, group.type) && Objects.equals(parentId, group.parentId) && Objects.equals(path, group.path) && Objects.equals(createTime, group.createTime) && Objects.equals(updateTime, group.updateTime) && Objects.equals(createBy, group.createBy) && Objects.equals(updateBy, group.updateBy) && Objects.equals(paths, group.paths) && Objects.equals(options, group.options);
}
@Override
public int hashCode() {
return Objects.hash(id, name, type, parentId, path, createTime, updateTime, createBy, updateBy, paths, options);
}
}
package org.ssssssss.magicapi.core.model;
/**
* Header参数信息
*
* @author mxd
*/
public class Header extends BaseDefinition {
public Header() {
}
public Header(String name, String value) {
super(name, value);
}
}
package org.ssssssss.magicapi.core.model;
/**
* 统一返回值对象
*
* @author mxd
*/
public class JsonBean<T> {
/**
* 状态码
*/
private int code = 1;
/**
* 状态说明
*/
private String message = "success";
/**
* 实际数据
*/
private T data;
/**
* 服务器时间
*/
private long timestamp = System.currentTimeMillis();
private Integer executeTime;
public JsonBean(int code, String message) {
this.code = code;
this.message = message;
}
public JsonBean(int code, String message, T data, Integer executeTime) {
this(code, message, data);
this.executeTime = executeTime;
}
public JsonBean(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public JsonBean() {
}
public JsonBean(JsonCode jsonCode) {
this(jsonCode, null);
}
public JsonBean(JsonCode jsonCode, T data) {
this(jsonCode.getCode(), jsonCode.getMessage(), data);
}
public JsonBean(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public Integer getExecuteTime() {
return executeTime;
}
public void setExecuteTime(Integer executeTime) {
this.executeTime = executeTime;
}
}
package org.ssssssss.magicapi.core.model;
/**
* 统一返回值对象带body
*
* @author mxd
*/
public class JsonBodyBean<T> extends JsonBean<T> {
private Object body;
public JsonBodyBean(int code, String message, T data, Object body) {
super(code, message, data);
this.body = body;
}
public JsonBodyBean(T data, Object body) {
super(data);
this.body = body;
}
public Object getBody() {
return body;
}
public void setBody(Object body) {
this.body = body;
}
}
package org.ssssssss.magicapi.core.model;
/**
* Json状态码信息
*
* @author mxd
*/
public class JsonCode {
private int code;
private String message;
public JsonCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public JsonCode format(Object... args) {
return new JsonCode(this.code, String.format(this.message, args));
}
}
package org.ssssssss.magicapi.core.model;
import java.util.Objects;
public class MagicEntity extends Attributes<Object> {
protected String id;
protected String script;
protected String groupId;
protected String name;
protected Long createTime;
protected Long updateTime;
protected String lock;
protected String createBy;
protected String updateBy;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
public Long getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Long updateTime) {
this.updateTime = updateTime;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLock() {
return lock;
}
public void setLock(String lock) {
this.lock = lock;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MagicEntity)) return false;
MagicEntity that = (MagicEntity) o;
return Objects.equals(id, that.id) && Objects.equals(script, that.script) && Objects.equals(groupId, that.groupId) && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(id, script, groupId, name);
}
public MagicEntity copy() {
MagicEntity entity = new MagicEntity();
copyTo(entity);
return entity;
}
public MagicEntity simple() {
MagicEntity entity = new MagicEntity();
simple(entity);
return entity;
}
protected void simple(MagicEntity entity) {
entity.setId(this.id);
entity.setName(this.name);
entity.setGroupId(this.groupId);
entity.setCreateBy(this.createBy);
entity.setCreateTime(this.createTime);
entity.setUpdateBy(this.updateBy);
entity.setUpdateTime(this.updateTime);
entity.setLock(this.lock);
}
protected void copyTo(MagicEntity entity) {
simple(entity);
entity.setScript(this.script);
entity.setProperties(this.properties);
}
}
package org.ssssssss.magicapi.core.model;
import org.ssssssss.magicapi.core.event.EventAction;
/**
* 消息通知对象
*
* @author mxd
*/
public class MagicNotify {
/**
* 消息来源(instanceId)
*/
private String from;
/**
* 文件或文件夹id
*/
private String id;
/**
* 动作
*/
private EventAction action = null;
/**
* 操作对象,如接口、函数、分组、数据源
*/
private String type = null;
/**
* WebSocket clientId
*/
private String clientId;
/**
* WebSocket消息内容
*/
private String content;
public MagicNotify() {
}
public MagicNotify(String from) {
this.from = from;
}
public MagicNotify(String from, EventAction action, String clientId, String content) {
this.from = from;
this.clientId = clientId;
this.action = action;
this.content = content;
}
public MagicNotify(String from, String id, EventAction action, String type) {
this.from = from;
this.id = id;
this.action = action;
this.type = type;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public EventAction getAction() {
return action;
}
public void setAction(EventAction action) {
this.action = action;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "MagicNotify{" +
"from='" + from + '\'' +
", id='" + id + '\'' +
", action=" + action +
", type='" + type + '\'' +
", clientId='" + clientId + '\'' +
", content='" + content + '\'' +
'}';
}
}
package org.ssssssss.magicapi.core.model;
public class Option extends BaseDefinition {
public Option() {
}
public Option(String name, String value) {
super(name, value);
}
public Option(String name, String value, String description) {
super(name, value);
setDescription(description);
}
}
package org.ssssssss.magicapi.core.model;
/**
* 接口选项信息
*
* @author mxd
*/
public enum Options {
/**
* 包装请求参数到一个变量中
*/
WRAP_REQUEST_PARAMETERS("包装请求参数到一个变量中", "wrap_request_parameter"),
/**
* 配置默认数据源的key
*/
DEFAULT_DATA_SOURCE("配置默认数据源的key", "default_data_source"),
/**
* 允许拥有该权限的访问
*/
PERMISSION("允许拥有该权限的访问", "permission"),
/**
* 允许拥有该角色的访问
*/
ROLE("允许拥有该角色的访问", "role"),
/**
* 该接口需要登录才允许访问
*/
REQUIRE_LOGIN("该接口需要登录才允许访问", "require_login", "true"),
/**
* 该接口需要不登录也可访问
*/
ANONYMOUS("该接口需要不登录也可访问", "anonymous", "true"),
/**
* 不接收未经定义的参数
*/
DISABLED_UNKNOWN_PARAMETER("不接收未经定义的参数", "disabled_unknown_parameter", "true"),
/**
* 禁止验证requestBody
*/
DISABLED_VALIDATE_REQUEST_BODY("禁止验证RequestBody", "disabled_validate_request_body", "false");
private final String name;
private final String value;
private final String defaultValue;
Options(String name, String value) {
this(name, value, null);
}
Options(String name, String value, String defaultValue) {
this.name = name;
this.value = value;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
public String getDefaultValue() {
return defaultValue;
}
}
package org.ssssssss.magicapi.core.model;
import java.util.Objects;
public final class Pair<S, T> {
private final S first;
private final T second;
private Pair(S first, T second) {
this.first = first;
this.second = second;
}
public static <S, T> Pair<S, T> of(S first, T second) {
return new Pair<>(first, second);
}
public S getFirst() {
return first;
}
public T getSecond() {
return second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Pair)) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(first, pair.first) && Objects.equals(second, pair.second);
}
@Override
public int hashCode() {
return Objects.hash(first, second);
}
}
package org.ssssssss.magicapi.core.model;
/**
* 参数信息
*
* @author mxd
*/
public class Parameter extends BaseDefinition {
public Parameter() {
}
public Parameter(String name, String value) {
super(name, value);
}
}
package org.ssssssss.magicapi.core.model;
/**
* 路径变量信息
*
* @author mxd
*/
public class Path extends BaseDefinition {
public Path() {
}
public Path(String name, String value) {
super(name, value);
}
@Override
public boolean isRequired() {
return true;
}
}
package org.ssssssss.magicapi.core.model;
public class PathMagicEntity extends MagicEntity {
/**
* 路径
*/
protected String path;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
protected void copyTo(PathMagicEntity entity) {
super.copyTo(entity);
entity.setPath(this.path);
}
protected void simple(PathMagicEntity entity) {
super.simple(entity);
entity.setPath(this.path);
}
}
package org.ssssssss.magicapi.core.model;
public class Plugin {
/**
* 插件名
*/
private final String name;
/**
* js全局变量名
*/
private String globalName;
/**
* js文件名
*/
private String javascriptFilename;
public Plugin(String name, String globalName, String javascriptFilename) {
this.name = name;
this.globalName = globalName;
this.javascriptFilename = javascriptFilename;
}
public Plugin(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getJavascriptFilename() {
return javascriptFilename;
}
public String getGlobalName() {
return globalName;
}
}
package org.ssssssss.magicapi.core.model;
/**
* 选择的资源
*
* @author mxd
*/
public class SelectedResource {
private String id;
private String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package org.ssssssss.magicapi.core.model;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class TreeNode<T> {
private T node;
private List<TreeNode<T>> children = new ArrayList<>();
public TreeNode() {
}
public TreeNode(T node) {
this.node = node;
}
public T getNode() {
return node;
}
public void setNode(T node) {
this.node = node;
}
public List<TreeNode<T>> getChildren() {
return children;
}
public void setChildren(List<TreeNode<T>> children) {
this.children = children;
}
public TreeNode<T> findTreeNode(Predicate<T> predicate) {
return findTreeNode(this.children, predicate);
}
private TreeNode<T> findTreeNode(List<TreeNode<T>> childs, Predicate<T> predicate) {
for (TreeNode<T> child : childs) {
if (predicate.test(child.getNode())) {
return child;
}
TreeNode<T> node = findTreeNode(child.children, predicate);
if (node != null) {
return node;
}
}
return null;
}
public void moveTo(TreeNode<T> node) {
node.children.add(this);
}
public List<T> flat() {
return flat(this);
}
private List<T> flat(TreeNode<T> node) {
List<T> result = new ArrayList<>();
result.add(node.getNode());
for (TreeNode<T> item : node.getChildren()) {
result.addAll(flat(item));
}
return result;
}
public void addChild(TreeNode<T> node) {
this.children.add(node);
}
}
package org.ssssssss.magicapi.core.resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.ssssssss.magicapi.utils.Assert;
import org.ssssssss.magicapi.utils.IoUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 数据库资源存储
*
* @author mxd
*/
public class DatabaseResource extends KeyValueResource {
private static final Logger logger = LoggerFactory.getLogger(DatabaseResource.class);
private final JdbcTemplate template;
private final String tableName;
private Map<String, String> cachedContent = new ConcurrentHashMap<>();
public DatabaseResource(JdbcTemplate template, String tableName) {
this(template, tableName, false);
}
public DatabaseResource(JdbcTemplate template, String tableName, boolean readonly) {
this(template, tableName, "/magic-api", readonly);
}
public DatabaseResource(JdbcTemplate template, String tableName, String path, boolean readonly) {
this(template, tableName, path, readonly, null);
}
public DatabaseResource(JdbcTemplate template, String tableName, String path, boolean readonly, KeyValueResource parent) {
super("/", path, readonly, parent);
this.template = template;
this.tableName = tableName;
}
public DatabaseResource(JdbcTemplate template, String tableName, String path, boolean readonly, Map<String, String> cachedContent, KeyValueResource parent) {
this(template, tableName, path, readonly, parent);
this.cachedContent = cachedContent;
}
@Override
public byte[] read() {
String value = this.cachedContent.get(path);
if (value == null) {
String sql = String.format("select file_content from %s where file_path = ?", tableName);
value = template.queryForObject(sql, String.class, this.path);
if (value != null) {
this.cachedContent.put(path, value);
}
}
return value == null ? new byte[0] : value.getBytes(StandardCharsets.UTF_8);
}
@Override
public void readAll() {
this.cachedContent.entrySet().removeIf(entry -> entry.getKey().startsWith(path));
String sql = String.format("select file_path, file_content from %s where file_path like '%s%%'", tableName, this.path);
SqlRowSet sqlRowSet = template.queryForRowSet(sql);
while (sqlRowSet.next()) {
Object object = sqlRowSet.getObject(2);
String content = null;
if (object instanceof String) {
content = object.toString();
} else if (object instanceof byte[]) {
content = new String((byte[]) object, StandardCharsets.UTF_8);
} else if (object instanceof Blob) {
Blob blob = (Blob) object;
try (InputStream is = blob.getBinaryStream()) {
content = new String(IoUtils.bytes(is), StandardCharsets.UTF_8);
} catch (SQLException | IOException ex) {
logger.error("读取content失败", ex);
}
} else if (object instanceof Clob) {
Clob clob = (Clob) object;
try {
content = clob.getSubString(1, (int) clob.length());
} catch (SQLException ex) {
logger.error("读取content失败", ex);
}
}
Assert.isNotNull(content, "读取content失败,请检查列类型是否正确");
this.cachedContent.put(sqlRowSet.getString(1), content);
}
}
@Override
public boolean exists() {
if (this.cachedContent.get(this.path) != null) {
return true;
}
String sql = String.format("select count(*) from %s where file_path = ?", tableName);
Long value = template.queryForObject(sql, Long.class, this.path);
return value != null && value > 0;
}
@Override
public boolean write(String content) {
String sql = String.format("update %s set file_content = ? where file_path = ?", tableName);
if (exists()) {
if (template.update(sql, content, this.path) > 0) {
this.cachedContent.put(this.path, content);
return true;
}
}
sql = String.format("insert into %s (file_path,file_content) values(?,?)", tableName);
if (template.update(sql, this.path, content) > 0) {
this.cachedContent.put(this.path, content);
return true;
}
return false;
}
@Override
public Set<String> keys() {
String prefix = isDirectory() ? this.path : (this.path + separator);
if (!cachedContent.isEmpty()) {
return cachedContent.keySet().stream().filter(it -> it.startsWith(prefix)).collect(Collectors.toSet());
}
String sql = String.format("select file_path from %s where file_path like '%s%%'", tableName, prefix);
return new HashSet<>(template.queryForList(sql, String.class));
}
@Override
public boolean renameTo(Map<String, String> renameKeys) {
List<Object[]> args = renameKeys.entrySet().stream().map(entry -> new Object[]{entry.getValue(), entry.getKey()}).collect(Collectors.toList());
String sql = String.format("update %s set file_path = ? where file_path = ?", tableName);
int affectedRows = Arrays.stream(template.batchUpdate(sql, args)).sum() ;
//oracle 执行更新操作成功会返回-2
if (affectedRows > 0 || affectedRows == -2) {
renameKeys.forEach((oldKey, newKey) -> this.cachedContent.put(newKey, this.cachedContent.remove(oldKey)));
return true;
}
return false;
}
@Override
public boolean delete() {
String sql = String.format("delete from %s where file_path = ? or file_path like '%s%%'", tableName, path);
if (template.update(sql, this.path) > 0) {
this.cachedContent.entrySet().removeIf(entry -> entry.getKey().startsWith(path));
return true;
}
return false;
}
@Override
public Function<String, Resource> mappedFunction() {
return it -> new DatabaseResource(template, tableName, it, readonly, this.cachedContent, this);
}
@Override
public String toString() {
return String.format("db://%s/%s", tableName, Objects.toString(this.path, ""));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment