Commit 45111d09 authored by Spencer Chang's avatar Spencer Chang

init

parent 94f03e01
# dp
# dp 数据处理中间件
## 实现DML DDL
## 数据修改
* 备份WHERE条件筛选的数据
* 检验WHERE条件筛选的数据条目与更新条目是否一致
* 禁止修改系统级别或业务系统基础数据
* DDL操作限制在内网环境使用
## v1-基础版本
### 直接判断sql语句关键字,校验sql有效性。
### 只支持单条语句执行并不需要结束符号。
## v2-多线程版本
### 使用Druid解析sql,校验sql有效性。
### 执行按钮支持以英文 **;** 分隔多条语句,使用多线程处理。
## 公共功能
### 查询只支持单条语句执行并不需要结束符号。
### 查询结果直接导出Excel。
### update & delete 语句默认会根据where条件先备份源数据。
### 每次执行的语句都会存储到数据库中(不管是否执行成功),并记录当前执行人ip、用户等信息。
## 支持版本
### Leaf4.1 & Leaf4.2
/* 数据处理(DP001) 注册脚本 */
resource_init(modules/DP/DP001/sys_dp.lview, 数据处理, HTML, Y, Y);
resource_init(sys/dp/query, 数据处理-查询);
resource_init(sys/dp/insert, 数据处理-查询);
resource_init(sys/dp/update, 数据处理-查询);
resource_init(sys/dp/delete, 数据处理-查询);
resource_init(sys/dp/ddl, 数据处理-ddl);
resource_init(sys/dp/download/log, 数据处理-日志下载);
/* 功能定义 */
function_init(DP001, 数据处理, Y, SYS, modules/DP/DP001/sys_dp.lview);
/* 功能资源分配 */
fun_resource(DP001, modules/DP/DP001/sys_dp.lview);
fun_resource(DP001, sys/dp/query);
fun_resource(DP001, sys/dp/insert);
fun_resource(DP001, sys/dp/update);
fun_resource(DP001, sys/dp/delete);
fun_resource(DP001, sys/dp/ddl);
fun_resource(DP001, sys/dp/download/log);
/* 角色功能分配 */
role_function(ADMIN, DP001);
\ No newline at end of file
create sequence sys_dp_execute_history_s;
\ No newline at end of file
sys_code_init(IP_ALLOW_LIST, IP允许访问列表, Y, USER, IP, "127.0.", Y);
\ No newline at end of file
create table sys_dp_execute_history
(
deh_id number not null,
deh_user_id number,
deh_ip varchar2(200),
deh_execute_time date,
deh_execute_type varchar2(10),
deh_row_count number,
deh_context clob,
deh_status varchar2(10),
deh_error varchar2(2000),
deh_bak_data clob,
OBJECT_VERSION_NUMBER number DEFAULT 1,
REQUEST_ID number DEFAULT -1,
PROGRAM_ID number DEFAULT -1,
CREATED_BY number DEFAULT -1,
CREATION_DATE date DEFAULT sysdate,
LAST_UPDATED_BY number DEFAULT -1,
LAST_UPDATE_DATE date DEFAULT sysdate,
LAST_UPDATE_LOGIN number DEFAULT -1
);
comment on table SYS_DP_EXECUTE_HISTORY
is '数据处理执行记录';
comment on column sys_dp_execute_history.deh_id
is 'PK';
comment on column sys_dp_execute_history.deh_user_id
is '执行人用户ID';
comment on column sys_dp_execute_history.deh_ip
is '执行IP';
comment on column sys_dp_execute_history.deh_execute_time
is '执行时间';
comment on column sys_dp_execute_history.deh_execute_type
is '执行类型 insert update delete query';
comment on column sys_dp_execute_history.deh_row_count
is '执行结果条数';
comment on column sys_dp_execute_history.deh_context
is '执行内容';
comment on column sys_dp_execute_history.deh_status
is '执行状态';
comment on column sys_dp_execute_history.deh_error
is '错误信息';
comment on column sys_dp_execute_history.deh_bak_data
is '备份源数据';
create index sys_dp_execute_history_n1 on sys_dp_execute_history(deh_user_id);
create index sys_dp_execute_history_n2 on sys_dp_execute_history(deh_ip);
alter table sys_dp_execute_history add constraint sys_dp_execute_history_pk primary key (deh_id);
\ No newline at end of file
package com.hand.hls.dp.controllers;
import com.hand.hap.core.IRequest;
import com.hand.hap.core.impl.RequestHelper;
import com.hand.hap.system.controllers.BaseController;
import com.hand.hap.system.dto.ResponseData;
import com.hand.hls.dp.service.SysDpDownloadLogService;
import com.hand.hls.dp.service.SysDpExecuteHistoryService;
import com.hand.hls.dp.util.IPUtils;
import leaf.bean.LeafRequestData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:31
* @since
*/
@RestController
public class SysDpExecuteHistoryController extends BaseController {
@Autowired
private SysDpExecuteHistoryService service;
@Autowired
private SysDpDownloadLogService downloadLogService;
@PostMapping(value = "/sys/dp/query")
public ResponseData query(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, @RequestParam("ck") int ck,
HttpServletRequest request, HttpServletResponse response) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
if (ck == 0){
service.query4ck(requestContext, ip, dpContext);
}else if(ck == 1){
request.setAttribute("_NO_PAGE_","Y");
final String context = new String(dpContext.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
service.query(requestContext, response, ip, context);
}
return new ResponseData();
}
@PostMapping(value = "/sys/dp/insert")
public ResponseData insert(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.insert(requestContext, ip, dpContext);
}
@PostMapping(value = "/sys/dp/update")
public ResponseData update(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.update(requestContext, ip, dpContext);
}
@PostMapping(value = "/sys/dp/delete")
public ResponseData delete(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.delete(requestContext, ip, dpContext);
}
@PostMapping(value = "/sys/dp/download/log")
public void downloadLog(HttpServletRequest request, HttpServletResponse response) throws Exception{
IRequest requestContext = createRequestContext(request);
downloadLogService.download(requestContext, request, response);
}
@PostMapping(value = "/sys/dp/ddl")
public void ddl(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
service.ddl(requestContext, ip, dpContext);
}
}
package com.hand.hls.dp.dto;
import com.hand.hap.mybatis.annotation.ExtensionAttribute;
import com.hand.hap.system.dto.BaseDTO;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
import java.util.Objects;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 16:01
* @since
*/
@ExtensionAttribute(disable = true)
@Table(name = "sys_dp_execute_history")
public class SysDpExecuteHistory extends BaseDTO {
@Id
@GeneratedValue
private Long dehId;
private Long dehUserId;
private String dehIp;
private Date dehExecuteTime;
private String dehExecuteType;
private Integer dehRowCount;
private String dehContext;
private String dehStatus;
private String dehError;
private String dehBakData;
public Long getDehId() {
return dehId;
}
public void setDehId(Long dehId) {
this.dehId = dehId;
}
public Long getDehUserId() {
return dehUserId;
}
public void setDehUserId(Long dehUserId) {
this.dehUserId = dehUserId;
}
public String getDehIp() {
return dehIp;
}
public void setDehIp(String dehIp) {
this.dehIp = dehIp;
}
public Date getDehExecuteTime() {
return dehExecuteTime;
}
public void setDehExecuteTime(Date dehExecuteTime) {
this.dehExecuteTime = dehExecuteTime;
}
public String getDehExecuteType() {
return dehExecuteType;
}
public void setDehExecuteType(String dehExecuteType) {
this.dehExecuteType = dehExecuteType;
}
public Integer getDehRowCount() {
return dehRowCount;
}
public void setDehRowCount(Integer dehRowCount) {
this.dehRowCount = dehRowCount;
}
public String getDehContext() {
return dehContext;
}
public void setDehContext(String dehContext) {
this.dehContext = dehContext;
}
public String getDehStatus() {
return dehStatus;
}
public void setDehStatus(String dehStatus) {
this.dehStatus = dehStatus;
}
public String getDehError() {
return dehError;
}
public void setDehError(String dehError) {
this.dehError = dehError;
}
public String getDehBakData() {
return dehBakData;
}
public void setDehBakData(String dehBakData) {
this.dehBakData = dehBakData;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SysDpExecuteHistory that = (SysDpExecuteHistory) o;
return Objects.equals(dehId, that.dehId) &&
Objects.equals(dehUserId, that.dehUserId) &&
Objects.equals(dehIp, that.dehIp) &&
Objects.equals(dehExecuteTime, that.dehExecuteTime) &&
Objects.equals(dehExecuteType, that.dehExecuteType) &&
Objects.equals(dehRowCount, that.dehRowCount) &&
Objects.equals(dehContext, that.dehContext) &&
Objects.equals(dehStatus, that.dehStatus) &&
Objects.equals(dehError, that.dehError) &&
Objects.equals(dehBakData, that.dehBakData);
}
@Override
public int hashCode() {
return Objects.hash(dehId, dehUserId, dehIp, dehExecuteTime, dehExecuteType, dehRowCount, dehContext, dehStatus, dehError, dehBakData);
}
@Override
public String toString() {
return "SysDpExecuteHistory{" +
"dehId=" + dehId +
", dehUserId=" + dehUserId +
", dehIp='" + dehIp + '\'' +
", dehExecuteTime=" + dehExecuteTime +
", dehExecuteType='" + dehExecuteType + '\'' +
", dehRowCount=" + dehRowCount +
", dehContext='" + dehContext + '\'' +
", dehStatus='" + dehStatus + '\'' +
", dehError='" + dehError + '\'' +
", dehBakData='" + dehBakData + '\'' +
'}';
}
}
package com.hand.hls.dp.mapper;
import com.hand.hap.mybatis.common.Mapper;
import com.hand.hls.dp.dto.SysDpExecuteHistory;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/5/12 19:17
* @since
*/
public interface SysDpExecuteHistoryMapper extends Mapper<SysDpExecuteHistory> {
}
package com.hand.hls.dp.service;
import com.hand.hap.core.IRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/20 10:02
* @since
*/
public interface SysDpDownloadLogService {
void download(IRequest requestContext, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
package com.hand.hls.dp.service;
import com.hand.hap.core.IRequest;
import com.hand.hap.core.ProxySelf;
import com.hand.hap.system.dto.ResponseData;
import com.hand.hap.system.service.IBaseService;
import com.hand.hls.dp.dto.SysDpExecuteHistory;
import javax.servlet.http.HttpServletResponse;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:57
* @since
*/
public interface SysDpExecuteHistoryService extends IBaseService<SysDpExecuteHistory>, ProxySelf<SysDpExecuteHistoryService> {
void query4ck(IRequest requestContext, final String ip, final String dpContext) throws Exception;
void query(IRequest requestContext, HttpServletResponse response, final String ip, final String dpContext) throws Exception;
ResponseData insert(IRequest requestContext, final String ip, final String dpContext);
ResponseData update(IRequest requestContext, final String ip, final String dpContext);
ResponseData delete(IRequest requestContext, final String ip, final String dpContext);
ResponseData ddl(IRequest requestContext, final String ip, final String dpContext);
void insertSysDpExecuteHistory(IRequest requestContext, SysDpExecuteHistory sysDpExecuteHistory);
}
package com.hand.hls.dp.service.impl;
import cn.hutool.core.date.DateUtil;
import com.hand.hap.core.IRequest;
import com.hand.hls.dp.service.SysDpDownloadLogService;
import com.hand.hls.dp.util.LogUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/20 10:03
* @since
*/
@Service
public class SysDpDownloadLogServiceImpl implements SysDpDownloadLogService {
@Value("${log-path}")
private String logPath;
@Override
public void download(IRequest requestContext, HttpServletRequest request, HttpServletResponse response) throws Exception {
String zipFileName = DateUtil.format(new Date(),"yyyyMMddHHmmss") + "_logs.zip";
response.reset();
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache,must-revalidate");
response.setHeader("Expires","0");
response.setHeader("Content-Disposition","attachment;filename=" + new String(zipFileName.getBytes(), StandardCharsets.ISO_8859_1));
response.setContentType("application/x-msdownload;");
ByteArrayOutputStream byteOutPut = new ByteArrayOutputStream();
CheckedOutputStream cos = new CheckedOutputStream(byteOutPut,new CRC32());
ZipOutputStream zos = new ZipOutputStream(cos);
// 下载7天内的日志
String[] downloadFiles = new String[7];
int length = downloadFiles.length;
// 当前日志
downloadFiles[0] = logPath + "leaf.log";
for (int i = 1; i <= length - 1;i++){
LocalDate tmp = LocalDate.now().minusDays(i);
Date date = Date.from(tmp.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
downloadFiles[i] = logPath + "leaf-" + DateUtil.format(new Date(),"yyyy-MM-dd") + ".log";
}
// 查找日志目录下所有文件
List<String> files = new ArrayList<>(30);
LogUtils.findFiles(new File(logPath),files);
files.forEach(file -> {
for (int i = 0; i < length; i++) {
if (file.equals(downloadFiles[i])) {
// 创建ZipEntry
ZipEntry entry = new ZipEntry(file.substring(logPath.length()));
// 放入文件,防止文件名相同的附件报错
try {
zos.putNextEntry(entry);
} catch (Exception e) {
// ignore
}
// 写入文件
LogUtils.readFileToZip(file,zos);
}
}
});
zos.closeEntry();
zos.close();
response.setHeader("Content-Length", String.valueOf(byteOutPut.size()));
IOUtils.copy(new ByteArrayInputStream(byteOutPut.toByteArray()), response.getOutputStream());
cos.close();
}
}
package com.hand.hls.dp.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import static java.util.Collections.emptyList;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/6/4 12:30
* @since
*/
public class ArrayUtils {
/**
* Indicates whether the given object is not {@code null} and is an array.
*
* @param o the given object.
* @return {@code true} if the given object is not {@code null} and is an array, otherwise {@code false}.
*/
public static boolean isArray(Object o) {
return o != null && o.getClass().isArray();
}
/**
* Indicates whether the given array is {@code null} or empty.
*
* @param <T> the type of elements of the array.
* @param array the array to check.
* @return {@code true} if the given array is {@code null} or empty, otherwise {@code false}.
*/
public static <T> boolean isNullOrEmpty(T[] array) {
return array == null || isEmpty(array);
}
/**
* Returns an array containing the given arguments.
*
* @param <T> the type of the array to return.
* @param values the values to store in the array.
* @return an array containing the given arguments.
*/
@SafeVarargs
public static <T> T[] array(T... values) {
return values;
}
/**
* Returns all the non-{@code null} elements in the given array.
*
* @param <T> the type of elements of the array.
* @param array the given array.
* @return all the non-{@code null} elements in the given array. An empty list is returned if the given array is
* {@code null}.
*/
public static <T> List<T> nonNullElementsIn(T[] array) {
if (array == null) {
return emptyList();
}
List<T> nonNullElements = new ArrayList<>();
for (T o : array) {
if (o != null) {
nonNullElements.add(o);
}
}
return nonNullElements;
}
/**
* Returns {@code true} if the given array has only {@code null} elements, {@code false} otherwise. If given array is
* empty, this method returns {@code true}.
*
* @param <T> the type of elements of the array.
* @param array the given array. <b>It must not be null</b>.
* @return {@code true} if the given array has only {@code null} elements or is empty, {@code false} otherwise.
* @throws NullPointerException if the given array is {@code null}.
*/
public static <T> boolean hasOnlyNullElements(T[] array) {
Objects.requireNonNull(array);
if (isEmpty(array)) {
return false;
}
for (T o : array) {
if (o != null) {
return false;
}
}
return true;
}
private static <T> boolean isEmpty(T[] array) {
return array.length == 0;
}
public static boolean isObjectArray(Object o) {
return isArray(o) && !isArrayTypePrimitive(o);
}
public static boolean isArrayTypePrimitive(Object o) {
return o != null && o.getClass().getComponentType().isPrimitive();
}
}
package com.hand.hls.dp.util;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.nio.Buffer;
import java.util.Objects;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:41
* @since
*/
public class IPUtils {
private static final String IPV4_LOCAL_HOST = "127.0.0.1";
private static final String IPV6_LOCAL_HOST = "0:0:0:0:0:0:0:1";
public static String getIpAddress(HttpServletRequest request) {
if (Objects.isNull(request)) {
return "";
}
// X-Forwarded-For:Squid 服务代理
String ip = request.getHeader("x-forwarded-for");
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// Proxy-Client-IP:apache 服务代理
ip = request.getHeader("Proxy-Client-IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// WL-Proxy-Client-IP:weblogic 服务代理
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// X-Real-IP:nginx服务代理
ip = request.getHeader("X-Real-IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
// 本地局域网放行
if (Objects.equals(IPV4_LOCAL_HOST,ip) || Objects.equals(IPV6_LOCAL_HOST,ip)) {
// 根据网卡获取本机配置的ip
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getLocalHost();
} catch (Exception e) {
// 默认
ip = IPV4_LOCAL_HOST;
}
byte[] address = inetAddress.getAddress();
if (address.length == 16) {
// IPV6
ip = inetAddress.getHostAddress();
} else if (address.length == 4) {
// IPV4
ip = inetAddress.getHostAddress();
} else {
//throw new Exception("Invalid IPv6 address: '" + ip + '\'');
// 默认
ip = IPV6_LOCAL_HOST;
}
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
// "***.***.***.***".length() = 15
if (Objects.nonNull(ip) && ip.length() > 15) {
if (ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
}
}
return extractString(ip);
}
/**
* 获取访问主机的网段(4位)
*/
private static String extractString(String s) {
if (StringUtils.isEmpty(s)) {
return "";
}
StringBuilder retVal = new StringBuilder();
String[] split = s.split("\\.");
for (int i = 0; i < 4; i++) {
retVal.append(split[i]);
if (i < 3) {
retVal.append(".");
}
}
return retVal.toString();
}
// private static final String inet6AddressToAscii(byte[] address) {
// int longestRunOffset = -1;
// int longestRunLength = 0;
// boolean var3 = false;
// boolean var4 = false;
// int var5 = false;
//
// for(int i = 0; i < address.length; i += 2) {
// int currentRunOffset;
// for(currentRunOffset = i; i < 16 && address[i] == 0 && address[i + 1] == 0; i += 2) {
// }
//
// int currentRunLength = i - currentRunOffset;
// if (currentRunLength > longestRunLength && currentRunLength >= 4) {
// longestRunOffset = currentRunOffset;
// longestRunLength = currentRunLength;
// }
// }
//
// Buffer result = new Buffer();
// int i = 0;
//
// while(i < address.length) {
// if (i == longestRunOffset) {
// result.writeByte(58);
// i += longestRunLength;
// if (i == 16) {
// result.writeByte(58);
// }
// } else {
// if (i > 0) {
// result.writeByte(58);
// }
//
// int group = Util.and(address[i], 255) << 8 | Util.and(address[i + 1], 255);
// result.writeHexadecimalUnsignedLong((long)group);
// i += 2;
// }
// }
//
// return result.readUtf8();
// }
}
package com.hand.hls.dp.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipOutputStream;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/20 10:19
* @since
*/
public class LogUtils {
private static final Logger logger = LoggerFactory.getLogger(LogUtils.class);
/**
* 兼容不同操作系统间区别
*/
private static final String separator = File.separator;
/** 默认缓存大小 */
public static final int DEFAULT_BUFFER_SIZE = 256;
/** 默认大缓存大小 */
public static final int DEFAULT_LARGE_BUFFER_SIZE = 1024;
/** 数据流末尾 */
public static final int EOF = -1;
/**
* 通过目录查找所属文件
* @param dir 待查询目录
* @param fileNames 查询结果
*/
public static void findFiles(File dir, List<String> fileNames){
Objects.requireNonNull(dir,"file dir must not be null");
if (!dir.exists() || !dir.isDirectory()) {
return;
}
String[] files = dir.list();
for (String s : Objects.requireNonNull(files)) {
File file = new File(dir, s);
if (file.isFile()) {
fileNames.add(dir + separator + file.getName());
} else {
findFiles(file, fileNames);
}
}
}
/**
* 读取文件内容写入ZipOutputStream
* @param filePath 待读取文件全路径
* @param zos 写入内容的ZipOutputStream
*/
public static void readFileToZip(final String filePath, ZipOutputStream zos){
Objects.requireNonNull(filePath,"filePath must not be null");
Objects.requireNonNull(zos,"ZipOutputStream must not be null");
try (RandomAccessFile raf = new RandomAccessFile(filePath,"r");
FileChannel fileChannel = raf.getChannel()){
ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_LARGE_BUFFER_SIZE);
int n = 0;
while (EOF != (n = fileChannel.read(buffer))) {
// 切换buffer读模式
buffer.flip();
while (buffer.hasRemaining()) {
int remain = buffer.remaining();
byte[] bytes = new byte[remain];
// 从buffer读取数据到bytes
buffer.get(bytes);
// 内容写入ZipOutputStream
zos.write(bytes,0,n);
}
// 切换buffer写模式
buffer.clear();
}
} catch (FileNotFoundException fe){
// 文件没找到
if (logger.isErrorEnabled()) {
logger.error("{} file not found!", filePath);
}
} catch (IOException e){
// io例外
if (logger.isWarnEnabled()) {
logger.warn("{} file IOException!Message:[{}]", filePath, e.getMessage());
}
}
}
}
package com.hand.hls.dp.util;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 16:25
* @since
*/
public interface SqlConstantUtils {
String SQL_STAR = "*";
String SQL_SELECT = "select";
String SQL_FROM = "from";
String SQL_FROM_UPPER = "FROM";
String SQL_WHERE = "where";
String SQL_WHERE_UPPER = "WHERE";
String SQL_WHERE_ADD = "and";
String SQL_WHERE_ADD_UPPER = "AND";
String SQL_UDPATE = "update";
String SQL_DELETE = "delete";
String SQL_DROP = "drop";
String SQL_TRUNCATE = "truncate";
String SQL_SET = "set";
String SQL_SET_UPPER = "SET";
String SQL_INSERT_INTO = "insert into";
String DDL_CREATE_TABLE = "create table";
String DDL_ALTER_TABLE = "alter table";
String DDL_COMMENT_TABLE = "comment on table";
String DDL_COMMENT_ON_COLUMN = "comment on column";
String DDL_CREATE_INDEX = "create index";
String DDL_CREATE_SEQUENCE = "create sequence";
String SQL_EXEC_SELECT = "SELECT";
String SQL_EXEC_INSERT = "INSERT";
String SQL_EXEC_UPDATE = "UPDATE";
String SQL_EXEC_DELETE = "DELETE";
String SQL_EXEC_DDL = "DDL";
String SQL_EXEC_DONE = "DONE";
String SQL_EXEC_DE = "DE";
String SQL_EXEC_UNDO = "UNDO";
String SQL_WHERE_1T1_EQ = "=";
String[] SQL_FILTER_TABLE = new String[]{"sys_dp_execute_history","QRTZ_","ACT_","SYS_USER","SYS_ROLE_B","SYS_FUNCTION_B","SYS_ROLE_FUNCTION",
"SYS_RESOURCE_B","SYS_JOB_RUNNING_INFO","SYS_MODULE","SYS_WIDGETS","USER_","DBA_",};
}
package com.hand.hls.dp.util;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Objects;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 16:37
* @since
*/
public class SqlUtils {
public static boolean checkSql(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
return false;
}
for (String condition : conditions) {
if (StringUtils.contains(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSql4WhereOneToOne(String sql) {
int lastIndex = StringUtils.lastIndexOfIgnoreCase(sql, SqlConstantUtils.SQL_WHERE);
String condition = StringUtils.substringAfterLast(sql, StringUtils.substring(sql, lastIndex, lastIndex + 5));
String[] conditions = StringUtils.split(StringUtils.trimToEmpty(condition), SqlConstantUtils.SQL_WHERE_ADD);
if (ArrayUtils.isNullOrEmpty(conditions)) {
conditions = StringUtils.split(condition, SqlConstantUtils.SQL_WHERE_ADD_UPPER);
}
for (String c : conditions) {
c = StringUtils.deleteWhitespace(StringUtils.normalizeSpace(c));
String[] tmpCons = StringUtils.split(c, SqlConstantUtils.SQL_WHERE_1T1_EQ);
if (!ArrayUtils.isNullOrEmpty(tmpCons)) {
List<String> cons = ArrayUtils.nonNullElementsIn(tmpCons);
cons.remove(SqlConstantUtils.SQL_WHERE_1T1_EQ);
for (int i = 0; i < cons.size(); i++) {
if (i == 1) {
String startCon = cons.get(i - 1);
String endCon = cons.get(i);
if (StringUtils.equals(startCon, endCon)) {
return true;
}
}
}
}
}
return false;
}
public static boolean checkSqlIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (StringUtils.containsIgnoreCase(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlFilterTableIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (StringUtils.containsIgnoreCase(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlStartWithIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (!StringUtils.startsWith(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlStartWith4DdlIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_CREATE_TABLE)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_ALTER_TABLE)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_COMMENT_TABLE)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_COMMENT_ON_COLUMN)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_CREATE_INDEX)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_CREATE_SEQUENCE)) {
return false;
}
for (String condition : conditions) {
if (StringUtils.startsWith(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlEndsWithIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (StringUtils.endsWithIgnoreCase(sql, condition)) {
return true;
}
}
return false;
}
}
package hls.core.sys.mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 此mapper只用于查询syscode相关的值,暂无其他方法
* Created by fjm on 2017/7/31.
*/
public interface SysCodeValueMapper {
String queryCodeValueMeaning(@Param("code") String code, @Param("code_value") String codeValue);
List<Map> queryCodeDetails(String code);
}
This diff is collapsed.
package com.hand.hls.dp.controllers;
import com.hand.hap.core.IRequest;
import com.hand.hap.core.impl.RequestHelper;
import com.hand.hap.system.controllers.BaseController;
import com.hand.hap.system.dto.ResponseData;
import com.hand.hls.dp.service.SysDpDownloadLogService;
import com.hand.hls.dp.service.SysDpExecuteHistoryService;
import com.hand.hls.dp.util.IPUtils;
import leaf.bean.LeafRequestData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:31
* @since
*/
@RestController
public class SysDpExecuteHistoryController extends BaseController {
@Autowired
private SysDpExecuteHistoryService service;
@Autowired
private SysDpDownloadLogService downloadLogService;
@PostMapping(value = "/sys/dp/query")
public ResponseData query(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, @RequestParam("ck") int ck,
HttpServletRequest request, HttpServletResponse response) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
if (ck == 0){
service.query4ck(requestContext, ip, dpContext);
}else if(ck == 1){
request.setAttribute("_NO_PAGE_","Y");
final String context = new String(dpContext.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
service.query(requestContext, response, ip, context);
}
return new ResponseData();
}
@PostMapping(value = "/sys/dp/insert")
public ResponseData insert(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.insert(requestContext, ip, dpContext);
}
@PostMapping(value = "/sys/dp/update")
public ResponseData update(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.update(requestContext, ip, dpContext);
}
@PostMapping(value = "/sys/dp/delete")
public ResponseData delete(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.delete(requestContext, ip, dpContext);
}
@PostMapping(value = "/sys/dp/download/log")
public void downloadLog(HttpServletRequest request, HttpServletResponse response) throws Exception{
IRequest requestContext = createRequestContext(request);
downloadLogService.download(requestContext, request, response);
}
@PostMapping(value = "/sys/dp/ddl")
public void ddl(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData, HttpServletRequest request) throws Exception{
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
service.ddl(requestContext, ip, dpContext);
}
}
package com.hand.hls.dp.controllers.v2;
import com.hand.hap.core.IRequest;
import com.hand.hap.core.impl.RequestHelper;
import com.hand.hap.system.controllers.BaseController;
import com.hand.hap.system.dto.ResponseData;
import com.hand.hls.dp.service.SysDpExecuteHistoryService;
import com.hand.hls.dp.util.IPUtils;
import leaf.bean.LeafRequestData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:31
* @since
*/
@RestController
public class SysDpExecuteHistoryV2Controller extends BaseController {
@Autowired
private SysDpExecuteHistoryService service;
@PostMapping(value = "/sys/dp/v2/execute")
public ResponseData query(@ModelAttribute(LEAF_PARAM_NAME) LeafRequestData requestData,
HttpServletRequest request) throws Exception {
IRequest requestContext = createRequestContext(request);
RequestHelper.setCurrentRequest(requestContext);
final String ip = IPUtils.getIpAddress(request);
final String dpContext = (String) requestData.get("parameter");
return service.execute(requestContext, ip, dpContext);
}
}
package com.hand.hls.dp.dto;
import com.hand.hap.mybatis.annotation.ExtensionAttribute;
import com.hand.hap.system.dto.BaseDTO;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
import java.util.Objects;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 16:01
* @since
*/
@ExtensionAttribute(disable = true)
@Table(name = "sys_dp_execute_history")
public class SysDpExecuteHistory extends BaseDTO {
@Id
@GeneratedValue
private Long dehId;
private Long dehUserId;
private String dehIp;
private Date dehExecuteTime;
private String dehExecuteType;
private Integer dehRowCount;
private String dehContext;
private String dehStatus;
private String dehError;
private String dehBakData;
public Long getDehId() {
return dehId;
}
public void setDehId(Long dehId) {
this.dehId = dehId;
}
public Long getDehUserId() {
return dehUserId;
}
public void setDehUserId(Long dehUserId) {
this.dehUserId = dehUserId;
}
public String getDehIp() {
return dehIp;
}
public void setDehIp(String dehIp) {
this.dehIp = dehIp;
}
public Date getDehExecuteTime() {
return dehExecuteTime;
}
public void setDehExecuteTime(Date dehExecuteTime) {
this.dehExecuteTime = dehExecuteTime;
}
public String getDehExecuteType() {
return dehExecuteType;
}
public void setDehExecuteType(String dehExecuteType) {
this.dehExecuteType = dehExecuteType;
}
public Integer getDehRowCount() {
return dehRowCount;
}
public void setDehRowCount(Integer dehRowCount) {
this.dehRowCount = dehRowCount;
}
public String getDehContext() {
return dehContext;
}
public void setDehContext(String dehContext) {
this.dehContext = dehContext;
}
public String getDehStatus() {
return dehStatus;
}
public void setDehStatus(String dehStatus) {
this.dehStatus = dehStatus;
}
public String getDehError() {
return dehError;
}
public void setDehError(String dehError) {
this.dehError = dehError;
}
public String getDehBakData() {
return dehBakData;
}
public void setDehBakData(String dehBakData) {
this.dehBakData = dehBakData;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SysDpExecuteHistory that = (SysDpExecuteHistory) o;
return Objects.equals(dehId, that.dehId) &&
Objects.equals(dehUserId, that.dehUserId) &&
Objects.equals(dehIp, that.dehIp) &&
Objects.equals(dehExecuteTime, that.dehExecuteTime) &&
Objects.equals(dehExecuteType, that.dehExecuteType) &&
Objects.equals(dehRowCount, that.dehRowCount) &&
Objects.equals(dehContext, that.dehContext) &&
Objects.equals(dehStatus, that.dehStatus) &&
Objects.equals(dehError, that.dehError) &&
Objects.equals(dehBakData, that.dehBakData);
}
@Override
public int hashCode() {
return Objects.hash(dehId, dehUserId, dehIp, dehExecuteTime, dehExecuteType, dehRowCount, dehContext, dehStatus, dehError, dehBakData);
}
@Override
public String toString() {
return "SysDpExecuteHistory{" +
"dehId=" + dehId +
", dehUserId=" + dehUserId +
", dehIp='" + dehIp + '\'' +
", dehExecuteTime=" + dehExecuteTime +
", dehExecuteType='" + dehExecuteType + '\'' +
", dehRowCount=" + dehRowCount +
", dehContext='" + dehContext + '\'' +
", dehStatus='" + dehStatus + '\'' +
", dehError='" + dehError + '\'' +
", dehBakData='" + dehBakData + '\'' +
'}';
}
}
package com.hand.hls.dp.mapper;
import com.hand.hap.mybatis.common.Mapper;
import com.hand.hls.dp.dto.SysDpExecuteHistory;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/5/12 19:17
* @since
*/
public interface SysDpExecuteHistoryMapper extends Mapper<SysDpExecuteHistory> {
}
package com.hand.hls.dp.service;
import com.hand.hap.core.IRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/20 10:02
* @since
*/
public interface SysDpDownloadLogService {
void download(IRequest requestContext, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
package com.hand.hls.dp.service;
import com.hand.hap.core.IRequest;
import com.hand.hap.core.ProxySelf;
import com.hand.hap.system.dto.ResponseData;
import com.hand.hap.system.service.IBaseService;
import com.hand.hls.dp.dto.SysDpExecuteHistory;
import javax.servlet.http.HttpServletResponse;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:57
* @since
*/
public interface SysDpExecuteHistoryService extends IBaseService<SysDpExecuteHistory>, ProxySelf<SysDpExecuteHistoryService> {
void query4ck(IRequest requestContext, final String ip, final String dpContext) throws Exception;
void query(IRequest requestContext, HttpServletResponse response, final String ip, final String dpContext) throws Exception;
ResponseData insert(IRequest requestContext, final String ip, final String dpContext);
ResponseData update(IRequest requestContext, final String ip, final String dpContext);
ResponseData delete(IRequest requestContext, final String ip, final String dpContext);
ResponseData ddl(IRequest requestContext, final String ip, final String dpContext);
void insertSysDpExecuteHistory(IRequest requestContext, SysDpExecuteHistory sysDpExecuteHistory);
ResponseData execute(IRequest requestContext, final String ip, final String dpContext) throws Exception;
}
package com.hand.hls.dp.service.impl;
import cn.hutool.core.date.DateUtil;
import com.hand.hap.core.IRequest;
import com.hand.hls.dp.service.SysDpDownloadLogService;
import com.hand.hls.dp.util.LogUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/20 10:03
* @since
*/
@Service
public class SysDpDownloadLogServiceImpl implements SysDpDownloadLogService {
@Value("${log-path}")
private String logPath;
@Override
public void download(IRequest requestContext, HttpServletRequest request, HttpServletResponse response) throws Exception {
String zipFileName = DateUtil.format(new Date(),"yyyyMMddHHmmss") + "_logs.zip";
response.reset();
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache,must-revalidate");
response.setHeader("Expires","0");
response.setHeader("Content-Disposition","attachment;filename=" + new String(zipFileName.getBytes(), StandardCharsets.ISO_8859_1));
response.setContentType("application/x-msdownload;");
ByteArrayOutputStream byteOutPut = new ByteArrayOutputStream();
CheckedOutputStream cos = new CheckedOutputStream(byteOutPut,new CRC32());
ZipOutputStream zos = new ZipOutputStream(cos);
// 下载7天内的日志
String[] downloadFiles = new String[7];
int length = downloadFiles.length;
// 当前日志
downloadFiles[0] = logPath + "leaf.log";
for (int i = 1; i <= length - 1;i++){
LocalDate tmp = LocalDate.now().minusDays(i);
Date date = Date.from(tmp.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
downloadFiles[i] = logPath + "leaf-" + DateUtil.format(new Date(),"yyyy-MM-dd") + ".log";
}
// 查找日志目录下所有文件
List<String> files = new ArrayList<>(30);
LogUtils.findFiles(new File(logPath),files);
files.forEach(file -> {
for (int i = 0; i < length; i++) {
if (file.equals(downloadFiles[i])) {
// 创建ZipEntry
ZipEntry entry = new ZipEntry(file.substring(logPath.length()));
// 放入文件,防止文件名相同的附件报错
try {
zos.putNextEntry(entry);
} catch (Exception e) {
// ignore
}
// 写入文件
LogUtils.readFileToZip(file,zos);
}
}
});
zos.closeEntry();
zos.close();
response.setHeader("Content-Length", String.valueOf(byteOutPut.size()));
IOUtils.copy(new ByteArrayInputStream(byteOutPut.toByteArray()), response.getOutputStream());
cos.close();
}
}
package com.hand.hls.dp.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import static java.util.Collections.emptyList;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/6/4 12:30
* @since
*/
public class ArrayUtils {
/**
* Indicates whether the given object is not {@code null} and is an array.
*
* @param o the given object.
* @return {@code true} if the given object is not {@code null} and is an array, otherwise {@code false}.
*/
public static boolean isArray(Object o) {
return o != null && o.getClass().isArray();
}
/**
* Indicates whether the given array is {@code null} or empty.
*
* @param <T> the type of elements of the array.
* @param array the array to check.
* @return {@code true} if the given array is {@code null} or empty, otherwise {@code false}.
*/
public static <T> boolean isNullOrEmpty(T[] array) {
return array == null || isEmpty(array);
}
/**
* Returns an array containing the given arguments.
*
* @param <T> the type of the array to return.
* @param values the values to store in the array.
* @return an array containing the given arguments.
*/
@SafeVarargs
public static <T> T[] array(T... values) {
return values;
}
/**
* Returns all the non-{@code null} elements in the given array.
*
* @param <T> the type of elements of the array.
* @param array the given array.
* @return all the non-{@code null} elements in the given array. An empty list is returned if the given array is
* {@code null}.
*/
public static <T> List<T> nonNullElementsIn(T[] array) {
if (array == null) {
return emptyList();
}
List<T> nonNullElements = new ArrayList<>();
for (T o : array) {
if (o != null) {
nonNullElements.add(o);
}
}
return nonNullElements;
}
/**
* Returns {@code true} if the given array has only {@code null} elements, {@code false} otherwise. If given array is
* empty, this method returns {@code true}.
*
* @param <T> the type of elements of the array.
* @param array the given array. <b>It must not be null</b>.
* @return {@code true} if the given array has only {@code null} elements or is empty, {@code false} otherwise.
* @throws NullPointerException if the given array is {@code null}.
*/
public static <T> boolean hasOnlyNullElements(T[] array) {
Objects.requireNonNull(array);
if (isEmpty(array)) {
return false;
}
for (T o : array) {
if (o != null) {
return false;
}
}
return true;
}
private static <T> boolean isEmpty(T[] array) {
return array.length == 0;
}
public static boolean isObjectArray(Object o) {
return isArray(o) && !isArrayTypePrimitive(o);
}
public static boolean isArrayTypePrimitive(Object o) {
return o != null && o.getClass().getComponentType().isPrimitive();
}
}
package com.hand.hls.dp.util;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.nio.Buffer;
import java.util.Objects;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 15:41
* @since
*/
public class IPUtils {
private static final String IPV4_LOCAL_HOST = "127.0.0.1";
private static final String IPV6_LOCAL_HOST = "0:0:0:0:0:0:0:1";
public static String getIpAddress(HttpServletRequest request) {
boolean ipv6 = false;
if (Objects.isNull(request)) {
return "";
}
// X-Forwarded-For:Squid 服务代理
String ip = request.getHeader("x-forwarded-for");
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// Proxy-Client-IP:apache 服务代理
ip = request.getHeader("Proxy-Client-IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// WL-Proxy-Client-IP:weblogic 服务代理
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// X-Real-IP:nginx服务代理
ip = request.getHeader("X-Real-IP");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (Objects.isNull(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
// 本地局域网放行
if (Objects.equals(IPV4_LOCAL_HOST,ip) || Objects.equals(IPV6_LOCAL_HOST,ip)) {
// 根据网卡获取本机配置的ip
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getLocalHost();
} catch (Exception e) {
// 默认
ip = IPV4_LOCAL_HOST;
}
byte[] address = inetAddress.getAddress();
if (address.length == 16) {
// IPV6
ip = inetAddress.getHostAddress();
ipv6 = true;
} else if (address.length == 4) {
// IPV4
ip = inetAddress.getHostAddress();
} else {
//throw new Exception("Invalid IPv6 address: '" + ip + '\'');
// 默认
ip = IPV6_LOCAL_HOST;
ipv6 = true;
}
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
// "***.***.***.***".length() = 15
if (Objects.nonNull(ip) && ip.length() > 15 && !ipv6) {
if (ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
}
}
return extractString(ip);
}
/**
* 获取访问主机的网段(4位)
*/
private static String extractString(String s) {
if (StringUtils.isEmpty(s)) {
return "";
}
StringBuilder retVal = new StringBuilder();
String[] split = s.split("\\.");
for (int i = 0; i < 4; i++) {
retVal.append(split[i]);
if (i < 3) {
retVal.append(".");
}
}
return retVal.toString();
}
// private static final String inet6AddressToAscii(byte[] address) {
// int longestRunOffset = -1;
// int longestRunLength = 0;
// boolean var3 = false;
// boolean var4 = false;
// int var5 = false;
//
// for(int i = 0; i < address.length; i += 2) {
// int currentRunOffset;
// for(currentRunOffset = i; i < 16 && address[i] == 0 && address[i + 1] == 0; i += 2) {
// }
//
// int currentRunLength = i - currentRunOffset;
// if (currentRunLength > longestRunLength && currentRunLength >= 4) {
// longestRunOffset = currentRunOffset;
// longestRunLength = currentRunLength;
// }
// }
//
// Buffer result = new Buffer();
// int i = 0;
//
// while(i < address.length) {
// if (i == longestRunOffset) {
// result.writeByte(58);
// i += longestRunLength;
// if (i == 16) {
// result.writeByte(58);
// }
// } else {
// if (i > 0) {
// result.writeByte(58);
// }
//
// int group = Util.and(address[i], 255) << 8 | Util.and(address[i + 1], 255);
// result.writeHexadecimalUnsignedLong((long)group);
// i += 2;
// }
// }
//
// return result.readUtf8();
// }
}
package com.hand.hls.dp.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipOutputStream;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/20 10:19
* @since
*/
public class LogUtils {
private static final Logger logger = LoggerFactory.getLogger(LogUtils.class);
/**
* 兼容不同操作系统间区别
*/
private static final String separator = File.separator;
/** 默认缓存大小 */
public static final int DEFAULT_BUFFER_SIZE = 256;
/** 默认大缓存大小 */
public static final int DEFAULT_LARGE_BUFFER_SIZE = 1024;
/** 数据流末尾 */
public static final int EOF = -1;
/**
* 通过目录查找所属文件
* @param dir 待查询目录
* @param fileNames 查询结果
*/
public static void findFiles(File dir, List<String> fileNames){
Objects.requireNonNull(dir,"file dir must not be null");
if (!dir.exists() || !dir.isDirectory()) {
return;
}
String[] files = dir.list();
for (String s : Objects.requireNonNull(files)) {
File file = new File(dir, s);
if (file.isFile()) {
fileNames.add(dir + separator + file.getName());
} else {
findFiles(file, fileNames);
}
}
}
/**
* 读取文件内容写入ZipOutputStream
* @param filePath 待读取文件全路径
* @param zos 写入内容的ZipOutputStream
*/
public static void readFileToZip(final String filePath, ZipOutputStream zos){
Objects.requireNonNull(filePath,"filePath must not be null");
Objects.requireNonNull(zos,"ZipOutputStream must not be null");
try (RandomAccessFile raf = new RandomAccessFile(filePath,"r");
FileChannel fileChannel = raf.getChannel()){
ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_LARGE_BUFFER_SIZE);
int n = 0;
while (EOF != (n = fileChannel.read(buffer))) {
// 切换buffer读模式
buffer.flip();
while (buffer.hasRemaining()) {
int remain = buffer.remaining();
byte[] bytes = new byte[remain];
// 从buffer读取数据到bytes
buffer.get(bytes);
// 内容写入ZipOutputStream
zos.write(bytes,0,n);
}
// 切换buffer写模式
buffer.clear();
}
} catch (FileNotFoundException fe){
// 文件没找到
if (logger.isErrorEnabled()) {
logger.error("{} file not found!", filePath);
}
} catch (IOException e){
// io例外
if (logger.isWarnEnabled()) {
logger.warn("{} file IOException!Message:[{}]", filePath, e.getMessage());
}
}
}
}
package com.hand.hls.dp.util;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLParserFeature;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Objects;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 16:37
* @since
*/
public class SqlCheckUtils {
private static final Logger logger = LoggerFactory.getLogger(SqlCheckUtils.class);
public static boolean checkSql(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
return false;
}
for (String condition : conditions) {
if (StringUtils.contains(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSql4WhereOneToOne(String sql) {
int lastIndex = StringUtils.lastIndexOfIgnoreCase(sql, SqlConstantUtils.SQL_WHERE);
String condition = StringUtils.substringAfterLast(sql, StringUtils.substring(sql, lastIndex, lastIndex + 5));
String[] conditions = StringUtils.split(StringUtils.trimToEmpty(condition), SqlConstantUtils.SQL_WHERE_ADD);
if (ArrayUtils.isNullOrEmpty(conditions)) {
conditions = StringUtils.split(condition, SqlConstantUtils.SQL_WHERE_ADD_UPPER);
}
for (String c : conditions) {
c = StringUtils.deleteWhitespace(StringUtils.normalizeSpace(c));
String[] tmpCons = StringUtils.split(c, SqlConstantUtils.SQL_WHERE_1T1_EQ);
if (!ArrayUtils.isNullOrEmpty(tmpCons)) {
List<String> cons = ArrayUtils.nonNullElementsIn(tmpCons);
cons.remove(SqlConstantUtils.SQL_WHERE_1T1_EQ);
for (int i = 0; i < cons.size(); i++) {
if (i == 1) {
String startCon = cons.get(i - 1);
String endCon = cons.get(i);
if (StringUtils.equals(startCon, endCon)) {
return true;
}
}
}
}
}
return false;
}
public static boolean checkSqlIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (StringUtils.containsIgnoreCase(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlFilterTableIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (StringUtils.containsIgnoreCase(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlStartWithIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (!StringUtils.startsWith(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlStartWith4DdlIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_CREATE_TABLE)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_ALTER_TABLE)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_COMMENT_TABLE)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_COMMENT_ON_COLUMN)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_CREATE_INDEX)) {
return false;
} else if (StringUtils.startsWith(sql, SqlConstantUtils.DDL_CREATE_SEQUENCE)) {
return false;
}
for (String condition : conditions) {
if (StringUtils.startsWith(sql, condition)) {
return true;
}
}
return false;
}
public static boolean checkSqlEndsWithIgnoreCase(String sql, String... conditions) {
Objects.requireNonNull(conditions, "conditions 条件不能为空");
if (conditions.length < 1) {
throw new IllegalArgumentException("conditions 条件不能为空");
}
for (String condition : conditions) {
if (StringUtils.endsWithIgnoreCase(sql, condition)) {
return true;
}
}
return false;
}
private final static SQLParserFeature[] FORMAT_DEFAULT_FEATURES = {
SQLParserFeature.KeepComments,
SQLParserFeature.EnableSQLBinaryOpExprGroup
};
public static String format(String sql, String dbType) {
return format(sql, dbType, null, null);
}
public static String format(String sql, String dbType, List<Object> parameters, SQLUtils.FormatOption option) throws ClassCastException, ParserException{
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, FORMAT_DEFAULT_FEATURES);
List<SQLStatement> statementList = parser.parseStatementList();
return SQLUtils.toSQLString(statementList, dbType, parameters, option);
}
}
package com.hand.hls.dp.util;
/**
* @author <a href="mailto:zhangnet14@gmail.com">Spencer Chang</a>
* @date 2020/4/18 16:25
* @since
*/
public interface SqlConstantUtils {
String SELECT_COUNT = "SELECT COUNT(*) AS TOTALCOUNT FROM ";
String SELECT_FROM = "SELECT * FROM ";
String SQL_STAR = "*";
String SQL_SELECT = "select";
String SQL_FROM = "from";
String SQL_FROM_UPPER = "FROM";
String SQL_WHERE = "where";
String SQL_WHERE_UPPER = "WHERE";
String SQL_WHERE_ADD = "and";
String SQL_WHERE_ADD_UPPER = "AND";
String SQL_UDPATE = "update";
String SQL_DELETE = "delete";
String SQL_DROP = "drop";
String SQL_TRUNCATE = "truncate";
String SQL_SET = "set";
String SQL_SET_UPPER = "SET";
String SQL_INSERT_INTO = "insert into";
String DDL_CREATE_TABLE = "create table";
String DDL_ALTER_TABLE = "alter table";
String DDL_COMMENT_TABLE = "comment on table";
String DDL_COMMENT_ON_COLUMN = "comment on column";
String DDL_CREATE_INDEX = "create index";
String DDL_CREATE_SEQUENCE = "create sequence";
String DDL_ALTER_SEQUENCE = "alter sequence";
String DDL_ALTER_SYSTEM_KILL_SESSION = "alter system kill session";
String SQL_EXEC_SELECT = "SELECT";
String SQL_EXEC_INSERT = "INSERT";
String SQL_EXEC_UPDATE = "UPDATE";
String SQL_EXEC_DELETE = "DELETE";
String SQL_EXEC_DDL = "DDL";
String SQL_EXEC_DONE = "DONE";
String SQL_EXEC_DE = "DE";
String SQL_EXEC_UNDO = "UNDO";
String SQL_WHERE_1T1_EQ = "=";
String[] SQL_FILTER_TABLE = new String[]{"sys_dp_execute_history","QRTZ_","ACT_","SYS_USER","SYS_ROLE_B","SYS_FUNCTION_B","SYS_ROLE_FUNCTION",
"SYS_RESOURCE_B","SYS_JOB_RUNNING_INFO","SYS_MODULE","SYS_WIDGETS","USER_","DBA_",};
}
This diff is collapsed.
package hls.core.sys.mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 此mapper只用于查询syscode相关的值,暂无其他方法
* Created by fjm on 2017/7/31.
*/
public interface SysCodeValueMapper {
String queryCodeValueMeaning(@Param("code") String code, @Param("code_value") String codeValue);
List<Map> queryCodeDetails(String code);
}
<?xml version="1.0" encoding="UTF-8"?>
<a:screen xmlns:a="http://www.leaf-framework.org/application" trace="true">
<a:init-procedure/>
<a:view>
<script><![CDATA[
function dp001_query() {
$('dp001_query_btn').disable();
let dpContext = document.getElementById('context_tta').value;
Leaf.showConfirm('${l:HLS.PROMPT}', '确认执行当前语句吗?', function okFun() {
Leaf.Masker.mask(Ext.getBody(), '正在执行...');
Leaf.request({
url: '${/request/@context_path}/sys/dp/query?ck=0',
para: dpContext,
success: function () {
let form = document.createElement("form");
form.target = "_export_dp_query_window";
form.method = "post";
let url = '${/request/@context_path}/sys/dp/query?ck=1';
let token = $jq('meta[name=_csrf]').attr('content');
form.action = url + (url.indexOf('?') == -1 ? '?' : '&') + 'r=' + Math.random() + '&_csrf=' + token;
let iframe = Ext.get('_export_dp_query_window') || new Ext.Template('<iframe id ="_export_dp_query_window" name="_export_dp_query_window" style="position:absolute;left:-1000px;top:-1000px;width:1px;height:1px;display:none"></iframe>').insertFirst(document.body, {}, true)
var s = document.createElement("input");
s.id = "_request_data";
s.type = 'hidden';
s.name = '_request_data';
let p = {"parameter": dpContext};
s.value = Ext.encode(p);
form.appendChild(s);
document.body.appendChild(form);
form.submit();
Ext.fly(form).remove();
setTimeout(function () {
$('dp001_query_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
}, 10000);
},
failure: function () {
$('dp001_query_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
},
error: function () {
$('dp001_query_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
},
scope: this
});
}, function cancel() {
$('dp001_query_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
}, 200, 100);
}
function dp001_exec() {
$('dp001_exec_btn').disable();
let dpContext = document.getElementById('context_tta').value;
Leaf.showConfirm('${l:HLS.PROMPT}', '确认执行当前语句吗?', function okFun() {
document.getElementById('result_tta').value = null;
Leaf.Masker.mask(Ext.getBody(), '正在执行...');
Leaf.request({
url: '${/request/@context_path}/sys/dp/v2/execute',
para: dpContext,
success: function (res) {
setTimeout(function () {
$('dp001_exec_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
if (res.success) {
Leaf.showMessage('提示', '执行完成!');
// document.getElementById('result_tta').value = res.error.message;
document.getElementById('result_tta').value = res.result.record;
}
}, 10000);
},
failure: function () {
$('dp001_exec_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
},
error: function () {
$('dp001_exec_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
},
scope: this
});
}, function cancel() {
$('dp001_exec_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
}, 200, 100);
}
function download_log() {
$('dp001_download_log_btn').disable();
Leaf.showConfirm('${l:HLS.PROMPT}', '确认下载日志吗?', function okFun() {
Leaf.Masker.mask(Ext.getBody(), '正在下载中...');
let form = document.createElement("form");
form.target = "_export_dp_log_window";
form.method = "post";
let url = '${/request/@context_path}/sys/dp/download/log';
let token = $jq('meta[name=_csrf]').attr('content');
form.action = url + (url.indexOf('?') == -1 ? '?' : '&') + 'r=' + Math.random() + '&_csrf=' + token;
let iframe = Ext.get('_export_dp_log_window') || new Ext.Template('<iframe id ="_export_dp_log_window" name="_export_dp_log_window" style="position:absolute;left:-1000px;top:-1000px;width:1px;height:1px;display:none"></iframe>').insertFirst(document.body, {}, true)
document.body.appendChild(form);
form.submit();
Ext.fly(form).remove();
setTimeout(function () {
$('dp001_download_log_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
}, 10000);
}, function cancel() {
$('dp001_download_log_btn').enable();
Leaf.Masker.unmask(Ext.getBody());
}, 200, 100);
}
]]></script>
<a:screenBody>
<a:screenTopToolbar>
<a:gridButton id="dp001_query_btn" click="dp001_query" text="查询"/>
<a:gridButton id="dp001_exec_btn" click="dp001_exec" text="执行"/>
<a:gridButton id="dp001_download_log_btn" click="download_log" text="日志下载"/>
</a:screenTopToolbar>
<a:fieldSet title="待执行">
<a:textArea id="context_tta" name="context" marginWidth="50" marginHeight="450"/>
</a:fieldSet>
<a:fieldSet title="结果">
<a:textArea id="result_tta" readOnly="true" name="result" marginWidth="50" marginHeight="560"/>
</a:fieldSet>
</a:screenBody>
</a:view>
</a:screen>
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