diff --git a/pom.xml b/pom.xml index 36ed6ed96..7f213c5cf 100644 --- a/pom.xml +++ b/pom.xml @@ -710,5 +710,23 @@ jersey-apache-connector 2.23.1 + + + org.quartz-scheduler + quartz + 2.2.1 + + + org.quartz-scheduler + quartz-jobs + 2.2.1 + + + + com.alibaba + druid + 1.1.10 + + diff --git a/src/main/java/com/nis/domain/ScheduleCfg.java b/src/main/java/com/nis/domain/ScheduleCfg.java new file mode 100644 index 000000000..27962c24b --- /dev/null +++ b/src/main/java/com/nis/domain/ScheduleCfg.java @@ -0,0 +1,43 @@ +package com.nis.domain; + +import com.nis.domain.configuration.BaseCfg; + +/** + * 定时任务信息 schedule_info + * @author ThinkPad + * + */ +public class ScheduleCfg extends BaseCfg{ + private static final long serialVersionUID = 7151915080876949497L; + + private String name;//定时任务名称,预留 + private String cronValid;//生效cron表达式 + private String cronInvalid;//失效cron表达式 + private String whereStr;//动态where 条件 + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public String getCronValid() { + return cronValid; + } + public void setCronValid(String cronValid) { + this.cronValid = cronValid; + } + public String getCronInvalid() { + return cronInvalid; + } + public void setCronInvalid(String cronInvalid) { + this.cronInvalid = cronInvalid; + } + public String getWhereStr() { + return whereStr; + } + public void setWhereStr(String whereStr) { + this.whereStr = whereStr; + } + + +} diff --git a/src/main/java/com/nis/domain/ScheduleExceInfo.java b/src/main/java/com/nis/domain/ScheduleExceInfo.java new file mode 100644 index 000000000..8dc3184c0 --- /dev/null +++ b/src/main/java/com/nis/domain/ScheduleExceInfo.java @@ -0,0 +1,66 @@ +package com.nis.domain; + +import java.util.Date; + +import com.nis.domain.configuration.BaseCfg; + +/** + * 定时任务执行信息 schedule_exce_log/schedule_exce_new + * `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增', + `schedule_id` bigint(20) NOT NULL COMMENT 'schedule_info 表的主键', + `exce_time` datetime DEFAULT NULL COMMENT '最新执行时间', + `issue_status` int(255) DEFAULT NULL COMMENT '下发状态:1:生效,0:失效', + `issue_result` int(255) DEFAULT NULL COMMENT '下发结果:1:成功,0:失败', + `error_info` varchar(255) DEFAULT NULL COMMENT '下发失败原因', + `compile_id` bigint(20) DEFAULT NULL COMMENT '编译id', + * @author fang + * + */ +public class ScheduleExceInfo extends BaseCfg{ + private static final long serialVersionUID = 7151915080876949497L; + + private Long scheduleId;//定时器id + private Date exceTime;//下发时间 + private Integer issueStatus;//下发 的状态 + private Integer issueResult;//下发结果 + private String errorInfo;//动态where 条件 + private Integer isIssue;//是否需要下发配置,1:需要,0:不需要 + + public Long getScheduleId() { + return scheduleId; + } + public void setScheduleId(Long scheduleId) { + this.scheduleId = scheduleId; + } + public Date getExceTime() { + return exceTime; + } + public void setExceTime(Date exceTime) { + this.exceTime = exceTime; + } + public Integer getIssueStatus() { + return issueStatus; + } + public void setIssueStatus(Integer issueStatus) { + this.issueStatus = issueStatus; + } + public Integer getIssueResult() { + return issueResult; + } + public void setIssueResult(Integer issueResult) { + this.issueResult = issueResult; + } + public String getErrorInfo() { + return errorInfo; + } + public void setErrorInfo(String errorInfo) { + this.errorInfo = errorInfo; + } + public Integer getIsIssue() { + return isIssue; + } + public void setIsIssue(Integer isIssue) { + this.isIssue = isIssue; + } + +} diff --git a/src/main/java/com/nis/domain/configuration/BaseCfg.java b/src/main/java/com/nis/domain/configuration/BaseCfg.java index f9f0cfb13..8be50fcbd 100644 --- a/src/main/java/com/nis/domain/configuration/BaseCfg.java +++ b/src/main/java/com/nis/domain/configuration/BaseCfg.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; import com.nis.domain.BaseEntity; +import com.nis.domain.ScheduleCfg; import com.nis.domain.SysMenu; import com.nis.util.Constants; import com.nis.util.StringUtil; @@ -60,6 +61,14 @@ public class BaseCfg extends BaseEntity implements Cloneable{ protected Integer compileIsIssued; protected String exType;//导出类型 protected String hColumns;//导出隐藏列 + /** + * 定时任务信息 + */ + //protected List schedules; + /** + * 定时任务信息,2019年1月18日18:54:53 修改 + */ + protected ScheduleCfg schedule; public String getExType() { return exType; @@ -971,5 +980,12 @@ public class BaseCfg extends BaseEntity implements Cloneable{ public void setDoBlackList(Integer doBlackList) { this.doBlackList = doBlackList; } + public ScheduleCfg getSchedule() { + return schedule; + } + public void setSchedule(ScheduleCfg schedule) { + this.schedule = schedule; + } + } diff --git a/src/main/java/com/nis/domain/maat/ToUpdateMaatBeanStatus.java b/src/main/java/com/nis/domain/maat/ToUpdateMaatBeanStatus.java index 869d7e249..f30bb806d 100644 --- a/src/main/java/com/nis/domain/maat/ToUpdateMaatBeanStatus.java +++ b/src/main/java/com/nis/domain/maat/ToUpdateMaatBeanStatus.java @@ -54,6 +54,8 @@ public class ToUpdateMaatBeanStatus implements Serializable{ @Expose private Integer isValid; @Expose + private Integer service; + @Expose @SerializedName("opTime") private Date auditTime; public Integer getCompileId() { @@ -74,6 +76,12 @@ public class ToUpdateMaatBeanStatus implements Serializable{ public void setAuditTime(Date auditTime) { this.auditTime = auditTime; } + public Integer getService() { + return service; + } + public void setService(Integer service) { + this.service = service; + } } public String getVersion() { diff --git a/src/main/java/com/nis/persistence/interceptor/ScheduleSelectInterceptor.java b/src/main/java/com/nis/persistence/interceptor/ScheduleSelectInterceptor.java new file mode 100644 index 000000000..335bb9c75 --- /dev/null +++ b/src/main/java/com/nis/persistence/interceptor/ScheduleSelectInterceptor.java @@ -0,0 +1,93 @@ +package com.nis.persistence.interceptor; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Plugin; +import org.apache.ibatis.plugin.Signature; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; +import org.apache.log4j.Logger; + +import com.nis.domain.ScheduleCfg; +import com.nis.domain.configuration.BaseCfg; +import com.nis.util.ServiceConfigTemplateUtil; +/** + * 定时任务 拦截器 + * 1、拦截 select 操作 + * 2、判断是否 form 查询配置主表 + * 3、如果是配置主表,查询对应的 scheduleCfg信息 + * @author fang + * + */ +@Intercepts({@Signature(type = Executor.class, + method = "query", + args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) +public class ScheduleSelectInterceptor extends BaseInterceptor{ + private static final long serialVersionUID = -265785145929843646L; + private static final Logger logger = Logger.getLogger(ScheduleSelectInterceptor.class); + + @Override + @SuppressWarnings("all") + public Object intercept(Invocation invocation) throws Throwable { + final MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; + final Executor executor = (Executor)invocation.getTarget(); + // select sql 查询结果 + Object result = invocation.proceed(); + if(result != null ) { + if(result instanceof Collection) { + Collection c = (Collection)result; +// if(c.size()==1) {//如果只查询一个 配置可以判定为是 form update 页面查询 + if(c.size() >0) {//配置列表需要查询是否为定时任务,所以需要遍历 + Iterator iterator = c.iterator(); + while(iterator.hasNext()){ + Object next = iterator.next(); + if(next instanceof BaseCfg) { + BaseCfg cfg = (BaseCfg)next; + //结果集的类名 + String simpleName = next.getClass().getSimpleName(); + //根据类名查找对应的 表名 + String tableName = ServiceConfigTemplateUtil.getCfgTableNameByClassName(simpleName); + if(tableName != null) {//是配置主表 + Configuration configuration = mappedStatement.getConfiguration(); + MappedStatement scheduleStmt = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.findScheduleList"); + ScheduleCfg sc = new ScheduleCfg(); + sc.setTableName(tableName); + sc.setCfgId(cfg.getCfgId()); + sc.setCompileId(cfg.getCompileId()); + //executor.clearLocalCache(); + List schedules = executor.query(scheduleStmt, sc, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); + if(schedules != null&& schedules.size() > 0) { + cfg.setSchedule(schedules.get(0)); + } + logger.debug(String.format("配置bean中赋值scheduleCfg,表名:%s,类名:%s,cfgId:%s,compileId:%s,schedules num:%s", tableName,simpleName,sc.getCfgId(),sc.getCompileId(),schedules==null?0:schedules.size())); + } + }else{ + break; + } + } + + } + } + } + return result; + } + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } + + @Override + public void setProperties(Properties properties) { + + } + +} diff --git a/src/main/java/com/nis/persistence/interceptor/ScheduleUpdateInterceptor.java b/src/main/java/com/nis/persistence/interceptor/ScheduleUpdateInterceptor.java new file mode 100644 index 000000000..91c28e274 --- /dev/null +++ b/src/main/java/com/nis/persistence/interceptor/ScheduleUpdateInterceptor.java @@ -0,0 +1,389 @@ +package com.nis.persistence.interceptor; + +import java.lang.reflect.Array; +import java.sql.SQLException; +import java.text.DateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.ParameterMapping; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Plugin; +import org.apache.ibatis.plugin.Signature; +import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.type.TypeHandlerRegistry; +import org.apache.log4j.Logger; +import org.springframework.beans.BeanUtils; + +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.google.common.collect.Lists; +import com.nis.domain.ScheduleCfg; +import com.nis.domain.ScheduleExceInfo; +import com.nis.domain.configuration.BaseCfg; +import com.nis.util.ServiceConfigTemplateUtil; +import com.nis.web.security.UserUtils; + +import jersey.repackaged.com.google.common.collect.Sets; +/** + * 定时任务 拦截器 + * 1、拦截insert,update,delete操作 + * 2、判断是否是需要下发配置的表 + * 3、如果是需要下发配置的表,则同时将数据保存到schedule_cfg表中,并调用定时任务 + * @author fang + * + */ +@Intercepts({@Signature( + type= Executor.class, + method = "update", + args = {MappedStatement.class,Object.class})}) +public class ScheduleUpdateInterceptor extends BaseInterceptor{ + private static final long serialVersionUID = -265785145929843646L; + private static final Logger logger = Logger.getLogger(ScheduleUpdateInterceptor.class); + + private static final String TABLE_NAME_INSERT_REG = "^\\s*insert\\s+into\\s+([\\w_-]+)\\s*\\("; + private static final Pattern TABLE_NAME_INSERT_PATTERN = Pattern.compile(TABLE_NAME_INSERT_REG, Pattern.CASE_INSENSITIVE);//大小写 + + private static final String TABLE_NAME_UPDATE_REG = "^\\s*update\\s+([\\w_-]+)"; + private static final Pattern TABLE_NAME_UPDATE_PATTERN = Pattern.compile(TABLE_NAME_UPDATE_REG, Pattern.CASE_INSENSITIVE);//大小写 + + private static final String TABLE_NAME_DELETE_REG = "^\\s*delete\\s+from\\s+([\\w_-]+)"; + private static final Pattern TABLE_NAME_DELETE_PATTERN = Pattern.compile(TABLE_NAME_DELETE_REG, Pattern.CASE_INSENSITIVE);//大小写 + /** + * 排除拦截的id + */ + private static final Set EXCLUDE_MAPPER_IDS = Sets.newHashSet(); + static { + EXCLUDE_MAPPER_IDS.add("com.nis.web.dao.SchedulerDao.updateCfgTableStatus"); + EXCLUDE_MAPPER_IDS.add("com.nis.web.dao.basics.ServiceDictInfoDao"); + } + /** + * is_valid 字段名 + */ + private static final String IS_VALID_COLUMN = "is_valid"; + /** + * is_audit 字段名 + */ + private static final String IS_AUDIT_COLUMN = "is_audit"; + + @Override + @SuppressWarnings("all") + public Object intercept(Invocation invocation) throws Throwable { + final MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; + final Executor executor = (Executor)invocation.getTarget(); + Object parameter = invocation.getArgs()[1];//被拦截的 sql 参数 + BoundSql boundSql = mappedStatement.getBoundSql(parameter); + Object result = invocation.proceed();//被拦截的 sql 操作 继续执行 + String curProceedId = mappedStatement.getId(); + //不需要拦截的操作直接返回结果 + if(EXCLUDE_MAPPER_IDS.contains(curProceedId)) { + return result; + } + String tableName = null;//操作的表名 + //mybatis 整个mapper 信息 + Configuration configuration = mappedStatement.getConfiguration(); + //被拦截的 sql语句 + String sql = boundSql.getSql(); + //所有需要拦截的表名 + Set tableNames = ServiceConfigTemplateUtil.getCompileTableName(); + + switch (mappedStatement.getSqlCommandType()) { + case INSERT://新增配置 + Matcher insertMatcher = TABLE_NAME_INSERT_PATTERN.matcher(sql); + tableName = insertMatcher.find()?insertMatcher.group(1):tableName; + if(tableName != null && tableNames.contains(tableName.toLowerCase())) { + insertCfg(executor,parameter, configuration,tableName); + } + break; + case UPDATE://更新配置 + Matcher updateMatcher = TABLE_NAME_UPDATE_PATTERN.matcher(sql); + tableName = updateMatcher.find()?updateMatcher.group(1):tableName; + if(tableName != null && tableNames.contains(tableName.toLowerCase())) { + updateCfg(executor,boundSql, configuration,tableName); + } + break; + case DELETE://删除配置 + Matcher deleteMatcher = TABLE_NAME_DELETE_PATTERN.matcher(sql); + tableName = deleteMatcher.find()?deleteMatcher.group(1):tableName; + if(tableName != null && tableNames.contains(tableName.toLowerCase())) { + deleteCfg(executor,parameter, configuration,tableName); + } + break; + default: + break; + } + logger.debug(sql); + return result; + } + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } + + + /** + * @throws SQLException + * + */ + @SuppressWarnings("all") + private void insertCfg(Executor executor,Object parameterObject,Configuration configuration,String tableName) throws SQLException { + List cfgList = Lists.newArrayList(); + //确保 单个,批量都适用 + if(parameterObject instanceof BaseCfg) {//单个添加 + BaseCfg baseCfg = (BaseCfg)parameterObject; + cfgList.add(baseCfg); + }else if(parameterObject instanceof Collection) { + Collection> bcCollection = (Collection>)parameterObject; + cfgList.addAll(bcCollection); + }else if(parameterObject.getClass().isArray()) { + int length = Array.getLength(parameterObject); + for(int i = 0;i< length;i++) { + BaseCfg baseCfg = (BaseCfg)Array.get(parameterObject, i); + cfgList.add(baseCfg); + } + } + //整理需要 insert 的 schedule_cfg 的数据 + List scheduleList = Lists.newArrayList(); + for(BaseCfg baseCfg : cfgList) { + baseCfg.setIsValid(0);//设置默认值 + baseCfg.setIsAudit(0);//设置默认值 + ScheduleCfg scList = copyScheduleCfgFromBaseCfg(baseCfg, tableName); + if(scList!=null){ + scheduleList.add(scList); + } + } + + if(scheduleList.size() > 0) { + for(ScheduleCfg sc : scheduleList) { + MappedStatement statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.insert"); + executor.update(statement, sc); + } + } + } + + /** + * + */ + @SuppressWarnings("all") + private void updateCfg(Executor executor,BoundSql boundSql,Configuration configuration,String tableName) throws SQLException { + /* + * 条件1: is_valid=0,is_audit=0; 未生效之前修改,来自修改页面 + *1、首先将所有相关定时任务信息取消 + *2、 新增 定时任务信息 + */ + Object parameterObject = boundSql.getParameterObject(); + if(parameterObject instanceof BaseCfg) { + BaseCfg bc = (BaseCfg)parameterObject; + Integer isValid = bc.getIsValid(); + Integer isAudit = bc.getIsAudit(); + Integer compileId = bc.getCompileId(); + Long cfgId = bc.getCfgId(); + if(isValid == 0 && isAudit == 0) { + ScheduleCfg sc = new ScheduleCfg(); + sc.setCompileId(compileId); + sc.setEditorId(bc.getEditorId()); + sc.setEditTime(bc.getEditTime()); + sc.setCfgId(cfgId); + //根据 compileId 删除之前的 + MappedStatement statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.deleteByCompileId"); + executor.update(statement, sc); + //新增 更改的 + ScheduleCfg schedule = copyScheduleCfgFromBaseCfg(bc, tableName); + if(schedule != null ) { + statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.insert"); + executor.update(statement, schedule); + //配置信息新增,或取消之后重新修改,需要修改 exce_new表的状态 + statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.updateScheduleExceNew"); + ScheduleExceInfo exceNew = new ScheduleExceInfo(); + exceNew.setCompileId(compileId); + exceNew.setIssueStatus(1); + exceNew.setIsIssue(1);//定时任务执行时需要下发配置 + executor.update(statement, exceNew); + } + return; + } + } + //完整的sql语句,已经完成 ? 替换 + String sql = showSql(configuration, boundSql); + log.debug(String.format("cfg update sql : " , sql)); + //其它剩余基本判定为 修改状态的 update + MySqlStatementParser parser = new MySqlStatementParser(sql); + MySqlUpdateStatement updateSqlStmt = (MySqlUpdateStatement)parser.parseStatement(); + List items = updateSqlStmt.getItems(); + /* 分别获取 is_audit & is_valid 的值*/ + Integer isValid = null; + Integer isAudit = null; + for(SQLUpdateSetItem item : items) { + if(IS_VALID_COLUMN.equalsIgnoreCase(item.getColumn().toString())) { + isValid = Integer.valueOf(item.getValue().toString()); + continue; + } + if(IS_AUDIT_COLUMN.equalsIgnoreCase(item.getColumn().toString())) { + isAudit = Integer.valueOf(item.getValue().toString()); + continue; + } + if(isValid != null && isAudit != null) { + break; + } + } + //isValid 和 isAudit 同时为空,目前发现有 取消来函的 update 操作有此情况 + if(isValid == null && isAudit == null) { + return; + } + //获取当前的update 条件 + String whereStr = updateSqlStmt.getWhere().toString(); + StringBuilder whereSb = new StringBuilder(); + whereSb.append(" and table_name = '"); + whereSb.append(tableName); + whereSb.append("' and ( "); + whereSb.append(whereStr); + whereSb.append(" )"); + //根据当前的 update 条件 查出所有符合条件的 schedule_cfg 数据 + MappedStatement scheduleStmt = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.findScheduleList"); + ScheduleCfg sc = new ScheduleCfg(); + sc.setWhereStr(whereSb.toString()); + List schedules = executor.query(scheduleStmt, sc, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); + if(schedules != null && schedules.size() > 0) {//有符合条件的 定时任务 + Set compileSet = Sets.newHashSet();//保存操作的所有 compileId + Date now = new Date();//当前时间 + //1、将符合条件的是 ScheduleCfg update del_flag = 0 + for(ScheduleCfg scfg : schedules) { + compileSet.add(scfg.getCompileId()); + scfg.setEditorId(UserUtils.getUser().getId()); + scfg.setEditTime(now); + MappedStatement statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.deleteByCompileId"); + executor.update(statement, scfg); + } + //2、把原信息 重新保存,并修改 is_valid ,is_audit 状态 + for(ScheduleCfg scfg : schedules) { + MappedStatement statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.insert"); + scfg.setIsValid(isValid); + scfg.setIsAudit(isAudit); + executor.update(statement, scfg); + } + //手动 审核通过,立即生效时 已经下发,修改 exce_new 表的是否需要下发字段为 不需要 : 0 + if(isValid == 1 && isAudit == 1) { + for(Integer ci : compileSet) { + MappedStatement statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.findScheduleExceNew"); + ScheduleExceInfo se = new ScheduleExceInfo(); + se.setCompileId(ci); + se.setIsValid(isValid); + List seList = executor.query(statement, se, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); + if(seList == null || seList.size() < 1) {//没有执行记录,新增一条 + //配置信息新增,或取消之后重新修改,需要修改 exce_new表的状态 + statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.insertScheduleExceNew"); + ScheduleExceInfo exceNew = new ScheduleExceInfo(); + exceNew.setCompileId(ci); + exceNew.setIssueStatus(1); + exceNew.setIsIssue(0);//已经下发,定时任务不需要下发 + exceNew.setExceTime(new Date()); + executor.update(statement, exceNew); + }else { + //配置信息新增,或取消之后重新修改,需要修改 exce_new表的状态 + statement = configuration.getMappedStatement("com.nis.web.dao.SchedulerDao.updateScheduleExceNew"); + ScheduleExceInfo exceNew = new ScheduleExceInfo(); + exceNew.setCompileId(ci); + exceNew.setIssueStatus(1); + exceNew.setIsIssue(0);//已经下发,定时任务不需要下发 + executor.update(statement, exceNew); + } + + } + } + } + } + + /** + * 暂时没有发现有 删除操作 + */ + @SuppressWarnings("all") + private void deleteCfg(Executor executor,Object parameterObject,Configuration configuration,String tableName) throws SQLException { + + } + + + + + /** + * 从 basecfg 实体类中获取 schedule cfg + * @param baseCfg + * @param tableName + * @return + */ + private ScheduleCfg copyScheduleCfgFromBaseCfg(BaseCfg baseCfg,String tableName){ + ScheduleCfg schedule = baseCfg.getSchedule(); + if(schedule != null ) { + BeanUtils.copyProperties(baseCfg, schedule,new String[]{"userRegion1","userRegion2","userRegion3","userRegion4","userRegion5"}); + schedule.setTableName(tableName); + } + return schedule; + } + + + /*如果参数是String,则添加单引号, 如果是日期,则转换为时间格式器并加单引号; 对参数是null和不是null的情况作了处理*/ + private static String getParameterValue(Object obj) { + String value = null; + if (obj instanceof String) { + value = "'" + obj.toString() + "'"; + } else if (obj instanceof Date) { + DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault()); + value = "'" + formatter.format(new Date()) + "'"; + } else { + if (obj != null) { + value = obj.toString(); + } else { + value = "null"; + } + } + return value; + } + + // 进行?的替换 + public static String showSql(Configuration configuration, BoundSql boundSql) { + Object parameterObject = boundSql.getParameterObject(); // 获取参数 + List parameterMappings = boundSql.getParameterMappings(); + String sql = boundSql.getSql().replaceAll("[\\s]+", " "); // sql语句中多个空格都用一个空格代替 + if (parameterMappings != null && parameterMappings.size() >0 && parameterObject != null) { + TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); // 获取类型处理器注册器,类型处理器的功能是进行java类型和数据库类型的转换
       // 如果根据parameterObject.getClass()可以找到对应的类型,则替换 + if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { + sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(parameterObject))); + + } else { + MetaObject metaObject = configuration.newMetaObject(parameterObject);// MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作 + for (ParameterMapping parameterMapping : parameterMappings) { + String propertyName = parameterMapping.getProperty(); + if (metaObject.hasGetter(propertyName)) { + Object obj = metaObject.getValue(propertyName); + sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj))); + } else if (boundSql.hasAdditionalParameter(propertyName)) { + Object obj = boundSql.getAdditionalParameter(propertyName); // 该分支是动态sql + sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj))); + }else{sql=sql.replaceFirst("\\?","缺失");}//打印出缺失,提醒该参数缺失并防止错位 + } + } + } + return sql; + } + + + @Override + public void setProperties(Properties properties) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/com/nis/quartz/ScheduleCfgJob.java b/src/main/java/com/nis/quartz/ScheduleCfgJob.java new file mode 100644 index 000000000..1016dc1cf --- /dev/null +++ b/src/main/java/com/nis/quartz/ScheduleCfgJob.java @@ -0,0 +1,519 @@ +package com.nis.quartz; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.quartz.CalendarIntervalScheduleBuilder; +import org.quartz.CalendarIntervalTrigger; +import org.quartz.CronScheduleBuilder; +import org.quartz.DateBuilder; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.Job; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.JobKey; +import org.quartz.PersistJobDataAfterExecution; +import org.quartz.ScheduleBuilder; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleScheduleBuilder; +import org.quartz.SimpleTrigger; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import org.quartz.impl.matchers.GroupMatcher; +import org.quartz.impl.triggers.CalendarIntervalTriggerImpl; +import org.quartz.impl.triggers.CronTriggerImpl; +import org.quartz.spi.MutableTrigger; + +import com.nis.domain.ScheduleCfg; +import com.nis.util.Constants; +import com.nis.util.DateUtil; +import com.nis.util.DateUtils; +import com.nis.util.StringUtils; +import com.nis.web.dao.SchedulerDao; +import com.nis.web.service.SpringContextHolder; + +/** + * 定时任务 配置定时任务加载 + * 1、每 n s 执行一次,每次读取 schedule_cfg 最新的数据 + * 2、删除或新增 定时任务 + * 3、单线程执行 + * @author fang + * + */ +@DisallowConcurrentExecution +@PersistJobDataAfterExecution +public class ScheduleCfgJob implements Job { + private static final Logger log = Logger.getLogger(ScheduleCfgJob.class); + + /** + * 状态组,格式:statusGroup-compileId + */ + private static final String STATUS_GROUP = "statusGroup-"; + private static final String STATUS_JOB = "STATUS-JOB"; + /** + * 生效标识:valid-cronexp + */ + private static final String VALID_KEY = "valid-"; + /** + * 失效标识:invalid-cronexp + */ + private static final String INVALID_KEY = "invalid-"; + private static final JobKey STATUS_JOBKEY = JobKey.jobKey(STATUS_JOB, "statusGroup"); + private static final JobDetail STATUS_JOBDETAIL = JobBuilder.newJob(ScheduleStatusJob.class) + .withIdentity(STATUS_JOBKEY) + .storeDurably(true) + .build(); + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + Scheduler scheduler = context.getScheduler(); + SchedulerDao dao = SpringContextHolder.getBean(SchedulerDao.class); + JobDataMap dataMap = context.getJobDetail().getJobDataMap(); + long scheduleCfgId = dataMap.get("scheduleCfgId") == null ? 0:dataMap.getLong("scheduleCfgId"); + long limit = dataMap.get("limit") == null ? 1000:dataMap.getLong("limit"); + log.info(String.format("定时配置任务开始执行,scheduleCfgId:%s,limit:%s",scheduleCfgId,limit )); + List newlyCfg = null; + int totalNum = 0; + do { + newlyCfg = dao.findNewlyCfg(scheduleCfgId, limit); + if(newlyCfg != null && newlyCfg.size() > 0) { + totalNum += newlyCfg.size(); + for(ScheduleCfg cfg : newlyCfg) {//先取消之前的定时配置 + Integer compileId = cfg.getCompileId(); + try { + //取消之前所有的 trigger + GroupMatcher groupMatcher= GroupMatcher.triggerGroupEquals(STATUS_GROUP + compileId); + Set triggerKeys = scheduler.getTriggerKeys(groupMatcher); + if(triggerKeys != null && triggerKeys.size() > 0) { + for(TriggerKey tk : triggerKeys) { + scheduler.unscheduleJob(tk); + } + log.info(String.format("定时任务取消成功,compile:%s", compileId)); + } + } catch (Exception e) { + log.error(String.format("定时任务取消异常,compileId:%s", compileId),e); + } + } + for(ScheduleCfg cfg : newlyCfg) { + Integer compileId = cfg.getCompileId(); + try { + //判断状态,重新添加最新的 trigger + Integer isValid = cfg.getIsValid(); + Integer isAudit = cfg.getIsAudit(); + //添加定时任务的条件 + if((isValid == 1 && isAudit == 1) || (isValid == 0 && isAudit == 0)) { + //添加定时任务,包括valid 和 invalid + addJob(scheduler, cfg); + log.info(String.format("定时任务添加成功,compile:%s", compileId)); + } + } catch (Exception e) { + log.error(String.format("定时任务更新异常,compileId:%s", compileId),e); + } + } + //最后 保存此次 最后的id + ScheduleCfg lastCfg = newlyCfg.get(newlyCfg.size() -1); + scheduleCfgId = lastCfg.getId(); + dataMap.put("scheduleCfgId", scheduleCfgId); + log.info(String.format("加载定时任务,total num :%s", newlyCfg.size())); + } + } while (newlyCfg != null && newlyCfg.size() > 0); + log.info(String.format("定时配置任务结束执行,total num:%s",totalNum)); + } + + + /** + * 将定时任务信息添加到 定时器框架中调度 + * @param scheduler + * @param cfg + * @throws SchedulerException + */ + /*public static void addJob(Scheduler scheduler,ScheduleCfg cfg) throws SchedulerException { + Integer compileId = cfg.getCompileId(); + String cronValid = cfg.getCronValid(); + String cronInvalid = cfg.getCronInvalid(); + Trigger validTrigger = createTrigger(cronValid, compileId, true, cfg); + Trigger invalidTrigger = createTrigger(cronInvalid, compileId, false, cfg); + boolean jobExist = scheduler.checkExists(STATUS_JOBKEY); + if(!jobExist) {//判断 job 是否存在,不存在添加 + scheduler.addJob(STATUS_JOBDETAIL, false); + } + boolean checkExists = scheduler.checkExists(validTrigger.getKey()); + if(!checkExists) {//判断 valid trigger 是否存在,不存在添加 + scheduler.scheduleJob(validTrigger); + }else { + log.warn(String.format("Trigger already exists:%s ", validTrigger.getKey().toString())); + } + checkExists = scheduler.checkExists(invalidTrigger.getKey()); + if(!checkExists) {//判断 invalid trigger 是否存在,不存在添加 + scheduler.scheduleJob(invalidTrigger); + }else { + log.warn(String.format("Trigger already exists:%s ", invalidTrigger.getKey().toString())); + } + }*/ + + + public static void addJob(Scheduler scheduler,ScheduleCfg cfg) throws SchedulerException { + List triList = createTrigger(cfg); + boolean jobExist = scheduler.checkExists(STATUS_JOBKEY); + if(!jobExist) {//判断 job 是否存在,不存在添加 + scheduler.addJob(STATUS_JOBDETAIL, false); + } + for(Trigger tri : triList) { + boolean checkExists = scheduler.checkExists(tri.getKey()); + if(!checkExists) {//判断 valid trigger 是否存在,不存在添加 + log.debug(String.format("定时任务添加,%s", tri.getKey())); + scheduler.scheduleJob(tri); + log.info(String.format("定时任务添加成功,%s", tri.getKey())); + }else { + log.warn(String.format("Trigger already exists:%s ", tri.getKey().toString())); + } + } + } + + /** + * 将页面配置的内容 转换成 trigger + * @param cfg + * @return + */ + public static List createTrigger(ScheduleCfg cfg){ + String mode = cfg.getUserRegion1().toUpperCase();//定时任务运行模式:一次,每天,每周,每月 + List triList = null; + switch (mode) { + case "SINGLE"://单次运行 + triList = createSimpleTrigger(cfg); + break; + case "EVERYDAY"://每天运行 0 0 0 2/1 * ? ,不符合要求,定义每天都执行,然后在 代码判断 间隔时间 + triList = createCalendarIntervalTrigger(cfg); + break; + case "EVERYWEEK"://每周运行 + triList = createCalendarIntervalTrigger(cfg); + break; + case "EVERYMONTH"://每月运行 + triList = createEveryMonthTrigger(cfg); + break; + default: + log.warn(String.format("unknown mode : %s ", mode)); + break; + } + return triList; + } + + + + + /** + * 将时间转换成 时分秒 + * @param time + * @return + */ + public static List parseTime(String time) { + if(StringUtils.isNoneBlank(time)) { + String[] split = time.split(":"); + List tl = new ArrayList(3); + for(String s : split) { + tl.add(Integer.valueOf(s)); + } + return tl; + } + return null; + } + + public static Trigger createCronTrigger(String cron,Integer compileId,boolean isValid,ScheduleCfg cfg) { + String triggerName = isValid ? (VALID_KEY + cron) : (INVALID_KEY + cron); + JobDataMap dataMap = new JobDataMap(); + dataMap.put("isValid", isValid); + dataMap.put("cfg", cfg); + return TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triggerName, STATUS_GROUP+compileId)) + .withSchedule(CronScheduleBuilder.cronSchedule(cron)) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .build(); + } + + + /** + * 一次执行 + * @param cfg + * @return + */ + public static List createSimpleTrigger(ScheduleCfg cfg){ + List triList = new ArrayList(); + Integer compileId = cfg.getCompileId(); + String cronValid = cfg.getCronValid(); + String cronInvalid = cfg.getCronInvalid(); + Date validDate = DateUtil.convertStringToDate(cronValid, Constants.COMMON_DATE_FORMAT); + Date invalidDate = DateUtil.convertStringToDate(cronInvalid, Constants.COMMON_DATE_FORMAT); + JobDataMap dataMap = new JobDataMap(); + dataMap.put("isValid", true); + dataMap.put("cfg", cfg); + String triName = VALID_KEY + cfg.getUserRegion1() + "_" + cronValid; + Trigger trigger = TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triName, STATUS_GROUP+compileId)) + .withSchedule(SimpleScheduleBuilder.simpleSchedule()) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .startAt(validDate) + .build(); + triList.add(trigger); + dataMap = new JobDataMap(); + dataMap.put("isValid", false); + dataMap.put("cfg", cfg); + triName = INVALID_KEY + cfg.getUserRegion1() + "_" + cronInvalid; + trigger = TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triName, STATUS_GROUP+compileId)) + .withSchedule(SimpleScheduleBuilder.simpleSchedule()) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .startAt(invalidDate) + .build(); + triList.add(trigger); + return triList; + } + + + /** + * 间隔 n 天 或 n 周执行 + * @param cfg + * @return + */ + public static List createCalendarIntervalTrigger(ScheduleCfg cfg) { + List triList = new ArrayList(); + Integer compileId = cfg.getCompileId(); + String cronValid = cfg.getCronValid(); + String cronInvalid = cfg.getCronInvalid(); + String dayOrWeek = cfg.getUserRegion1(); + Integer interval = Integer.valueOf(cfg.getUserRegion2()); + List validList = parseTime(cronValid); + List invalidList = parseTime(cronInvalid); + Date validStartTime = DateBuilder.todayAt(validList.get(0), validList.get(1), validList.get(2)); + Date invalidTime = DateBuilder.todayAt(invalidList.get(0), invalidList.get(1), invalidList.get(2)); + CalendarIntervalScheduleBuilder intervalBuilder = null; + if("EVERYDAY".equalsIgnoreCase(dayOrWeek)) { + intervalBuilder = CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withIntervalInDays(interval); + //valid + JobDataMap dataMap = new JobDataMap(); + dataMap.put("isValid", true); + dataMap.put("cfg", cfg); + String triName = VALID_KEY + dayOrWeek+"("+interval+")" + "_" + DateUtils.formatDate(validStartTime, Constants.COMMON_DATE_FORMAT); + Trigger validTri = TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triName, STATUS_GROUP+compileId)) + .withSchedule(intervalBuilder) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .startAt(validStartTime) + .build(); + triList.add(validTri); + //invalid + dataMap = new JobDataMap(); + dataMap.put("isValid", false); + dataMap.put("cfg", cfg); + triName = INVALID_KEY + dayOrWeek +"("+interval+")" + "_" + DateUtils.formatDate(invalidTime, Constants.COMMON_DATE_FORMAT); + validTri = TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triName, STATUS_GROUP+compileId)) + .withSchedule(intervalBuilder) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .startAt(invalidTime) + .build(); + triList.add(validTri); + }else if("EVERYWEEK".equalsIgnoreCase(dayOrWeek)) { + intervalBuilder = CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withIntervalInWeeks(interval); + String[] weeks = cfg.getUserRegion3().split(","); + for(String week : weeks) { + if(StringUtils.isNoneBlank(week)) { + Date temp = closestAfterWeek(validStartTime, Integer.valueOf(week)); + JobDataMap dataMap = new JobDataMap(); + dataMap.put("isValid", true); + dataMap.put("cfg", cfg); + String triName = VALID_KEY + dayOrWeek +week+"("+interval+")" + "_" + DateUtils.formatDate(temp, Constants.COMMON_DATE_FORMAT); + Trigger validTri = TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triName, STATUS_GROUP+compileId)) + .withSchedule(intervalBuilder) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .startAt(temp) + .build(); + triList.add(validTri); + //invalid + dataMap = new JobDataMap(); + dataMap.put("isValid", false); + dataMap.put("cfg", cfg); + temp = closestAfterWeek(invalidTime, Integer.valueOf(week)); + triName = INVALID_KEY + dayOrWeek +week+"("+interval+")" + "_" + DateUtils.formatDate(temp, Constants.COMMON_DATE_FORMAT); + validTri = TriggerBuilder.newTrigger() + .withIdentity(createTiggerKey(triName, STATUS_GROUP+compileId)) + .withSchedule(intervalBuilder) + .usingJobData(dataMap) + .forJob(STATUS_JOBDETAIL) + .startAt(temp) + .build(); + triList.add(validTri); + } + } + } + return triList; + } + + /** + * 每月 执行 + * @param cfg + * @return + */ + public static List createEveryMonthTrigger(ScheduleCfg cfg){ + String dayWeek = cfg.getUserRegion3(); + String cronInvalid = cfg.getCronInvalid(); + String cronValid = cfg.getCronValid(); + StringBuilder cronSb = new StringBuilder(); + Trigger trigger = null; + List validList = parseTime(cronValid);//time 转换 + List invalidList = parseTime(cronInvalid);//time 转换 + List triList = new ArrayList(); + String userRegion4 = cfg.getUserRegion4().toUpperCase(); + if("day".equalsIgnoreCase(dayWeek)) {//指定天 + boolean hasL = userRegion4.contains("L"); + StringBuilder chooseSb = new StringBuilder(); + for(String str : userRegion4.split(",")) { + if(!"L".equalsIgnoreCase(str.trim())) { + chooseSb.append(",").append(str); + } + } + chooseSb.deleteCharAt(0); + cronSb.append(validList.get(2)).append(" ")//秒 + .append(validList.get(1)).append(" ")//分 + .append(validList.get(0)).append(" ")//小时 + .append(chooseSb.toString()).append(" ")//日 + .append(cfg.getUserRegion2()).append(" ")//月 + .append("?").append(" ");//周 + trigger = createCronTrigger(cronSb.toString(), cfg.getCompileId(), true, cfg); + triList.add(trigger); + cronSb.setLength(0); + cronSb.append(invalidList.get(2)).append(" ")//秒 + .append(invalidList.get(1)).append(" ")//分 + .append(invalidList.get(0)).append(" ")//小时 + .append(chooseSb.toString()).append(" ")//日 + .append(cfg.getUserRegion2()).append(" ")//月 + .append("?").append(" ");//周 + trigger = createCronTrigger(cronSb.toString(), cfg.getCompileId(), false, cfg); + triList.add(trigger); + if(hasL) {// 月的最后一天,quartz 不支持 1,L 这种指定,所以 L单独处理一下 + cronSb.setLength(0); + cronSb.append(validList.get(2)).append(" ")//秒 + .append(validList.get(1)).append(" ")//分 + .append(validList.get(0)).append(" ")//小时 + .append("L").append(" ")//日 + .append(cfg.getUserRegion2()).append(" ")//月 + .append("?").append(" ");//周 + trigger = createCronTrigger(cronSb.toString(), cfg.getCompileId(), true, cfg); + triList.add(trigger); + cronSb.setLength(0); + cronSb.append(invalidList.get(2)).append(" ")//秒 + .append(invalidList.get(1)).append(" ")//分 + .append(invalidList.get(0)).append(" ")//小时 + .append("L").append(" ")//日 + .append(cfg.getUserRegion2()).append(" ")//月 + .append("?").append(" ");//周 + trigger = createCronTrigger(cronSb.toString(), cfg.getCompileId(), false, cfg); + triList.add(trigger); + } + }else if ("week".equalsIgnoreCase(dayWeek)) {//指定周,1#2: 第一周的周二,4L:最后一周的周四 + for(String nthWeek : userRegion4.split(",")) {//第几周 + for(String week : cfg.getUserRegion5().split(",")) {//星期几 + cronSb.setLength(0); + cronSb.append(validList.get(2)).append(" ")//秒 + .append(validList.get(1)).append(" ")//分 + .append(validList.get(0)).append(" ")//小时 + .append("?").append(" ")//日 + .append(cfg.getUserRegion2()).append(" ");//月 + if("L".equalsIgnoreCase(nthWeek)) { + cronSb.append(week).append("L");//周 + }else { + cronSb.append(week).append("#").append(nthWeek);//周 + } + trigger = createCronTrigger(cronSb.toString(), cfg.getCompileId(), true, cfg); + triList.add(trigger); + cronSb.setLength(0); + cronSb.append(invalidList.get(2)).append(" ")//秒 + .append(invalidList.get(1)).append(" ")//分 + .append(invalidList.get(0)).append(" ")//小时 + .append("?").append(" ")//日 + .append(cfg.getUserRegion2()).append(" ");//月 + if("L".equalsIgnoreCase(nthWeek)) { + cronSb.append(week).append("L");//周 + }else { + cronSb.append(week).append("#").append(nthWeek);//周 + } + trigger = createCronTrigger(cronSb.toString(), cfg.getCompileId(), false, cfg); + triList.add(trigger); + } + } + } + return triList; + } + + + /** + * 查找最近的 星期几 ,包括今天 + * @param date + * @param w 周一开始 1 -7 + * @return + */ + public static Date closestAfterWeek(Date date,int w) { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + int i = cal.get(Calendar.DAY_OF_WEEK);//周日开始 1-7 + i = (i==1)? 7: i-1;//转换为 周一到 周日 1-7 + cal.add(Calendar.DAY_OF_MONTH, (i>w)?(7-(i-w)) : (w-i)); + return cal.getTime(); + } + + + public static TriggerKey createTiggerKey(String name,String group) { + TriggerKey key = new TriggerKey(name, group); + return key; + } + + /** + * jquery cron 生成的cron 表达式,quartz 不能直接使用,需要做些修改 + * @param cron + * @return + */ + public static String modifyCronExp(String cron) { + String[] cronArr = cron.split("\\s"); + if("*".equals(cronArr[4])) { + cronArr[4] = "?"; + }else { + cronArr[3] = "*"; + cronArr[2] = "?"; + } + return "0 " + StringUtils.join(cronArr, " "); + } + + + public static void main(String[] args) { + + CronTriggerImpl cron = new CronTriggerImpl(); + try { + String exp = "0 0 0 ? 1,2 1#4"; + cron.setCronExpression(exp); + System.out.println(cron); + } catch (ParseException e) { + e.printStackTrace(); + } + + + } + +} diff --git a/src/main/java/com/nis/quartz/ScheduleStatusJob.java b/src/main/java/com/nis/quartz/ScheduleStatusJob.java new file mode 100644 index 000000000..3d2de4d60 --- /dev/null +++ b/src/main/java/com/nis/quartz/ScheduleStatusJob.java @@ -0,0 +1,38 @@ +package com.nis.quartz; + +import org.apache.log4j.Logger; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import com.nis.domain.ScheduleCfg; +import com.nis.web.service.ScheduleService; +import com.nis.web.service.SpringContextHolder; + +/** + * 定时任务 真正执行类 + * 配置状态下发 + * 从trigger 的 jobDataMap 中取出 相关数据:compile,isValid + * @author fang + * + */ +public class ScheduleStatusJob implements Job{ + private static final Logger log = Logger.getLogger(ScheduleStatusJob.class); + + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + //从trigger中 获取 配置信息 + JobDataMap jobDataMap = context.getTrigger().getJobDataMap(); + boolean isValid = jobDataMap.getBoolean("isValid"); + ScheduleCfg cfg = (ScheduleCfg)jobDataMap.get("cfg"); + Integer compileId = cfg.getCompileId(); + log.debug(String.format("任务开始执行,compileId:%s,isValid:%s",compileId,isValid )); + //配置下发,并修改 配置表的状态,保存下发记录等 + ScheduleService scheduleService = SpringContextHolder.getBean(ScheduleService.class); + scheduleService.issueCompileInfo(cfg, isValid?1:0); + log.debug(String.format("任务开始执行,compileId:%s,isValid:%s",compileId,isValid )); + } + +} diff --git a/src/main/java/com/nis/util/ConfigConvertUtil.java b/src/main/java/com/nis/util/ConfigConvertUtil.java new file mode 100644 index 000000000..4d17ae576 --- /dev/null +++ b/src/main/java/com/nis/util/ConfigConvertUtil.java @@ -0,0 +1,690 @@ +package com.nis.util; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; + +import com.google.common.collect.Lists; +import com.googlecode.ipv6.IPv6Address; +import com.googlecode.ipv6.IPv6Network; +import com.nis.domain.basics.AsnIpCfg; +import com.nis.domain.configuration.AppIpCfg; +import com.nis.domain.configuration.BaseCfg; +import com.nis.domain.configuration.BaseIpCfg; +import com.nis.domain.configuration.BaseStringCfg; +import com.nis.domain.configuration.ComplexkeywordCfg; +import com.nis.domain.configuration.FileDigestCfg; +import com.nis.domain.configuration.IpPortCfg; +import com.nis.domain.maat.MaatCfg.DigestCfg; +import com.nis.domain.maat.MaatCfg.GroupCfg; +import com.nis.domain.maat.MaatCfg.IpCfg; +import com.nis.domain.maat.MaatCfg.NumBoundaryCfg; +import com.nis.domain.maat.MaatCfg.StringCfg; + +public class ConfigConvertUtil { + private static Logger logger = LoggerFactory.getLogger(ConfigConvertUtil.class); + /** + * 配置域转换 + * @param ipList + * @param strList + * @param complexStrList + * @param numList + * @param fileList + * @param regionIds + * @param groupIds + * @param entity + * @param compileId + * @param auditTime + * @param groupRelationList + * @param ipRegionList + * @param strRegionList + * @param numRegionList + * @param digestRegionList + * @param areaIpRegionList + * @param userRegion + */ + public static String configCovert(List ipList,List strList,List complexStrList, + List numList, + List fileList,List regionIds,List groupIds,BaseCfg entity, + Integer compileId,Date auditTime,List groupRelationList, + List ipRegionList, + List strRegionList, + List numRegionList, + List digestRegionList, + List areaIpRegionList,String userRegion){ + List list1 = new ArrayList(); + List list2 = new ArrayList(); + List list3 = new ArrayList(); + List list4 = new ArrayList(); + List list5 = new ArrayList(); + if(ipList.size()>0){ + for(int index=0;index0){ + ipList.removeAll(list1); + Map map = cfgToMaatConvert(ipRegionList,list1,1,groupRelationList); + groupRelationList=map.get("groupList"); + ipRegionList=map.get("dstList"); + if(map.get("numRegionList")!=null){ + numRegionList.addAll(map.get("numRegionList")); + } + } + if(list2.size()>0){ + strList.removeAll(list2); + Map map = cfgToMaatConvert(strRegionList,list2,2,groupRelationList); + groupRelationList=map.get("groupList"); + strRegionList=map.get("dstList"); + } + if(list3.size()>0){ + complexStrList.removeAll(list3); + Map map = cfgToMaatConvert(strRegionList,list3,3,groupRelationList); + groupRelationList=map.get("groupList"); + strRegionList=map.get("dstList"); + } + if(list4.size()>0){ + numList.removeAll(list4); + Map map = cfgToMaatConvert(numRegionList,list4,4,groupRelationList); + groupRelationList=map.get("groupList"); + numRegionList=map.get("dstList"); + } + if(list5.size()>0){ + fileList.removeAll(list5); + Map map = cfgToMaatConvert(digestRegionList,list5,5,groupRelationList); + groupRelationList=map.get("groupList"); + digestRegionList=map.get("dstList"); + } + return userRegion; + } + // asn IP 复用转换 + public static List groupReuseCfgAddRemoveConvert(List> ipCfgList, Integer isValid, + Integer groupId) { + logger.warn("convert data start"); + long start = System.currentTimeMillis(); + Date opTime = new Date(); + List maatIpList = new ArrayList<>(); + if (ipCfgList.size() > 0) { + // 只用一次instanceof,取代循环中每次都用一次instanceof + if (ipCfgList.get(0) instanceof AsnIpCfg) { + for (BaseCfg _cfg : ipCfgList) { + IpCfg cfg = new IpCfg(); + BaseIpCfg baseIpCfg = new BaseIpCfg(); + AsnIpCfg asnIpCfg = (AsnIpCfg) _cfg; + BeanUtils.copyProperties(asnIpCfg, baseIpCfg); + BeanUtils.copyProperties(baseIpCfg, cfg); + cfg.setGroupId(asnIpCfg.getAsnIpGroup()); + cfg.setRegionId(asnIpCfg.getRegionId()); + String userRegion = "ASN_ID=" + asnIpCfg.getUserRegion1(); + cfg.setUserRegion(userRegion); + cfg.setIsValid(isValid); + cfg.setAuditTime(opTime); + List cfgs = ipConvert(cfg, baseIpCfg); + maatIpList.addAll(cfgs); + } + } else if (ipCfgList.get(0) instanceof AppIpCfg) { + for (BaseCfg _cfg : ipCfgList) { + IpCfg cfg = new IpCfg(); + BaseIpCfg baseIpCfg = new BaseIpCfg(); + AppIpCfg appIpCfg = (AppIpCfg) _cfg; + BeanUtils.copyProperties(appIpCfg, baseIpCfg); + BeanUtils.copyProperties(baseIpCfg, cfg); + cfg.setGroupId(groupId); + cfg.setRegionId(Integer.parseInt(appIpCfg.getUserRegion1())); + String userRegion = "APP_ID=" + appIpCfg.getAppCode(); + cfg.setUserRegion(userRegion); + cfg.setIsValid(isValid); + cfg.setAuditTime(opTime); + List cfgs = ipConvert(cfg, baseIpCfg); + maatIpList.addAll(cfgs); + } + } + } + long end = System.currentTimeMillis(); + logger.warn("convert data finish,cost:" + (end - start)); + return maatIpList; + } + /** + * 界面配置list转换为服务接口端的list,用于批量下发时,regionId,groupId已在该方法前被批量获取 + * + * @param + * @param + * @param dstList + * @param srcList + * @param cfgType,1为IP类型,2为字符串类型,3为增强字符串,4数值类型,5摘要类,6回调类[但字符串类域配置和增强字符串域配置在接口参数中同属于strRegionList] + * @param baseCfg,配置基本信息 + * @param groupRelationList + * 配置分组列表 + * @return + */ + public static Map cfgToMaatConvert(List dstList, List srcList, Integer cfgType,List groupRelationList) { + Map map = new HashMap(); + if (cfgType == 1) { + List numRegionList = new ArrayList(); + Integer groupId = 0; + Integer numGroupId = 0; + for (int i = 0; i < srcList.size(); i++) { + List regionIdList = Lists.newArrayList(); + T srcCfg = srcList.get(i); + BaseIpCfg baseIpCfg = new BaseIpCfg(); + BeanUtils.copyProperties(srcCfg, baseIpCfg); + regionIdList.add(baseIpCfg.getRegionId()); + IpCfg cfg = new IpCfg(); + BeanUtils.copyProperties(baseIpCfg, cfg); + //多条IP配置属于同一个分组 + if (groupId == 0) { + GroupCfg group = new GroupCfg(); + groupId = baseIpCfg.getGroupId(); + group.setGroupId(groupId); + group.setCompileId(baseIpCfg.getCompileId()); + group.setAuditTime(baseIpCfg.getAuditTime()); + group.setIsValid(baseIpCfg.getIsValid()); + groupRelationList.add(group); + } + cfg.setGroupId(groupId); + cfg.setAuditTime(baseIpCfg.getAuditTime()); + cfg.setIsValid(baseIpCfg.getIsValid()); + List cfgs = ipConvert(cfg, baseIpCfg); + if (cfgs.size() > 1) { + List ids = ConfigServiceUtil.getId(3, cfgs.size() - 1); + regionIdList.addAll(ids); + } + for (int j = i; j < cfgs.size() + i; j++) { + cfgs.get(j - i).setRegionId(regionIdList.get(j)); + } + dstList.addAll(cfgs); + + // 如果protocolId非空非零,需要构造数值型域配置,多条相同协议的IP只需要一条数值域配置(目前没有不同协议IP&情况) + if (baseIpCfg.getProtocolId() != null && baseIpCfg.getProtocolId() != 0) { + if (numGroupId == 0) { + GroupCfg group1 = new GroupCfg(); + group1.setGroupId(ConfigServiceUtil.getId(2, 1).get(0)); + group1.setCompileId(baseIpCfg.getCompileId()); + group1.setAuditTime(baseIpCfg.getAuditTime()); + group1.setIsValid(baseIpCfg.getIsValid()); + groupRelationList.add(group1); + NumBoundaryCfg numCfg = new NumBoundaryCfg(); + numCfg.initDefaultValue(); + numCfg.setLowBoundary(baseIpCfg.getProtocolId()); + numCfg.setUpBoundary(baseIpCfg.getProtocolId()); + numCfg.setRegionId(ConfigServiceUtil.getId(3, 1).get(0)); + numCfg.setAuditTime(baseIpCfg.getAuditTime()); + numCfg.setGroupId(group1.getGroupId()); + numCfg.setIsValid(baseIpCfg.getIsValid()); + numRegionList.add(numCfg); + map.put("numRegionList", numRegionList); + numGroupId++; + } + } + } + + } else if (cfgType == 2 || cfgType == 3) { + for (int i = 0; i < srcList.size(); i++) { + // 一条业务配置创建一个分组 + BaseCfg baseCfg = new BaseCfg(); + BeanUtils.copyProperties(srcList.get(i), baseCfg,new String[]{"menuNameCode"});//拷贝公共属性 + GroupCfg group = new GroupCfg(); + StringCfg cfg = new StringCfg(); + BeanUtils.copyProperties(srcList.get(i), cfg,new String[]{"menuNameCode"});//拷贝公共属性以及私有属性 + group.setGroupId(baseCfg.getGroupId()); + group.setCompileId(baseCfg.getCompileId()); + group.setAuditTime(baseCfg.getAuditTime()); + group.setIsValid(baseCfg.getIsValid()); + groupRelationList.add(group); + cfg.setGroupId(group.getGroupId()); + cfg.setRegionId(baseCfg.getRegionId()); + cfg.setAuditTime(baseCfg.getAuditTime()); + cfg.setIsValid(baseCfg.getIsValid()); + // 处理配置关键字转译 + cfg.setCfgKeywords(keywordsEscape(cfg.getCfgKeywords())); + // 增强字符串转换 + cfg.setDistrict(keywordsEscape(cfg.getDistrict())); + dstList.add(cfg); + } + } else if (cfgType == 4) { + for (int i = 0; i < srcList.size(); i++) { + BaseCfg baseCfg = new BaseCfg(); + BeanUtils.copyProperties(srcList.get(i), baseCfg);//拷贝公共属性 + // 一条业务配置创建一个分组 + com.nis.domain.maat.MaatCfg.NumBoundaryCfg cfg = new com.nis.domain.maat.MaatCfg.NumBoundaryCfg(); + BeanUtils.copyProperties(srcList.get(i), cfg); + GroupCfg group = new GroupCfg(); + group.setGroupId(baseCfg.getGroupId()); + group.setCompileId(baseCfg.getCompileId()); + group.setAuditTime(baseCfg.getAuditTime()); + group.setIsValid(baseCfg.getIsValid()); + groupRelationList.add(group); + cfg.setGroupId(group.getGroupId()); + cfg.setRegionId(baseCfg.getRegionId()); + cfg.setAuditTime(baseCfg.getAuditTime()); + cfg.setIsValid(baseCfg.getIsValid()); + dstList.add(cfg); + } + } else if (cfgType == 5) { + for (int i = 0; i < srcList.size(); i++) { + BaseCfg baseCfg = new BaseCfg(); + BeanUtils.copyProperties(srcList.get(i), baseCfg);//拷贝公共属性 + // 一条业务配置创建一个分组 + com.nis.domain.maat.MaatCfg.DigestCfg cfg = new com.nis.domain.maat.MaatCfg.DigestCfg(); + BeanUtils.copyProperties(srcList.get(i), cfg); + GroupCfg group = new GroupCfg(); + group.setGroupId(baseCfg.getGroupId()); + group.setCompileId(baseCfg.getCompileId()); + group.setAuditTime(baseCfg.getAuditTime()); + group.setIsValid(baseCfg.getIsValid()); + groupRelationList.add(group); + cfg.setGroupId(group.getGroupId()); + cfg.setRegionId(baseCfg.getRegionId()); + cfg.setAuditTime(baseCfg.getAuditTime()); + cfg.setIsValid(baseCfg.getIsValid()); + dstList.add(cfg); + } + } else { + dstList.addAll(srcList); + } + map.put("groupList", groupRelationList); + map.put("dstList", dstList); + return map; + } + /** + * 关键字特殊字符转义处理 + * @param cfgKeywords + * @return + */ + public static String keywordsEscape(String cfgKeywords) { + if (StringUtils.isNotEmpty(cfgKeywords)) { + // 不转译特殊字符 + cfgKeywords = cfgKeywords.trim();// 首先去掉首尾空格 + cfgKeywords = StringEscapeUtils.unescapeHtml4(cfgKeywords); + cfgKeywords = cfgKeywords.replace("\\", "\\\\"); + cfgKeywords = cfgKeywords.replace("&", "\\&"); + cfgKeywords = cfgKeywords.replace(" ", "\\b"); + // ***and***在界面表示多个关键字的与表达式,此特殊字符串在common.js中使用定义,maat端以&表示 + cfgKeywords = cfgKeywords.replace(Constants.KEYWORD_EXPR, "&"); + + } + return cfgKeywords; + } + /** + * 界面IP配置转换为MAAT类或者回调类IP配置 + * + * @param dstIp + * @param srcIp + * @return + */ + public static List ipConvert(IpCfg dstIp, BaseIpCfg srcIp) { + List ipConvertList = Lists.newArrayList(); + boolean isRange = ((srcIp.getIpPattern() != null && srcIp.getIpPattern() == 2) + || (srcIp.getSrcIpAddress() != null && srcIp.getSrcIpAddress().indexOf("-") > -1) + || (srcIp.getDestIpAddress() != null && srcIp.getDestIpAddress().indexOf("-") > -1)); + if (isRange) { + List tempList = Lists.newArrayList(); + List tempList1 = Lists.newArrayList(); + if (srcIp.getIpType().intValue() == 4) { + if (srcIp.getSrcIpAddress() != null) { + String startIpPart = srcIp.getSrcIpAddress().split("-")[0]; + String endIpPart = srcIp.getSrcIpAddress().split("-")[1]; + Integer startNum = Integer.parseInt(startIpPart.split("\\.")[3]); + Integer endNum = Integer.parseInt(endIpPart.split("\\.")[3]); + for (int i = startNum; i <= endNum; i++) { + IpCfg tempIp = new IpCfg(); + BeanUtils.copyProperties(dstIp, tempIp); + tempIp.setSrcIp(startIpPart.substring(0, startIpPart.lastIndexOf(".") + 1) + i); + tempIp.setSrcIpMask("255.255.255.255"); + tempList.add(tempIp); + } + } else { + dstIp.setSrcIp("0.0.0.0"); + dstIp.setSrcIpMask("255.255.255.255"); + tempList.add(dstIp); + } + if (srcIp.getDestIpAddress() != null) { + String startIpPart = srcIp.getDestIpAddress().split("-")[0]; + String endIpPart = srcIp.getDestIpAddress().split("-")[1]; + Integer startNum = Integer.parseInt(startIpPart.split("\\.")[3]); + Integer endNum = Integer.parseInt(endIpPart.split("\\.")[3]); + for (IpCfg _cfg : tempList) { + for (int i = startNum; i <= endNum; i++) { + IpCfg tempIp = new IpCfg(); + BeanUtils.copyProperties(_cfg, tempIp); + tempIp.setDstIp(startIpPart.substring(0, startIpPart.lastIndexOf(".") + 1) + i); + tempIp.setDstIpMask("255.255.255.255"); + // 处理 + convertPortValues(tempIp, srcIp); + if (!tempIp.getSrcIp().equals(tempIp.getDstIp())) { + tempList1.add(tempIp); + } + + } + } + tempList.clear(); + } else { + for (IpCfg _cfg : tempList) { + _cfg.setDstIp("0.0.0.0"); + _cfg.setSrcIpMask("255.255.255.255"); + convertPortValues(_cfg, srcIp); + } + } + if (tempList1.size() > 0) { + ipConvertList.addAll(tempList1); + } else { + ipConvertList.addAll(tempList); + } + } else if (srcIp.getIpType().intValue() == 6) { + if (srcIp.getSrcIpAddress() != null) { + IPv6Address address1 = IPv6Address.fromString(srcIp.getSrcIpAddress().split("-")[0]); + IPv6Address address2 = IPv6Address.fromString(srcIp.getSrcIpAddress().split("-")[1]); + IPv6Network network = IPv6Network.fromTwoAddresses(address1, address2); + dstIp.setSrcIp(address1.toString()); + dstIp.setSrcIpMask(network.getNetmask().asAddress().toString()); + } else { + dstIp.setSrcIp("::"); + dstIp.setSrcIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); + } + if (srcIp.getDestIpAddress() != null) { + IPv6Address address1 = IPv6Address.fromString(srcIp.getDestIpAddress().split("-")[0]); + IPv6Address address2 = IPv6Address.fromString(srcIp.getDestIpAddress().split("-")[1]); + IPv6Network network = IPv6Network.fromTwoAddresses(address1, address2); + dstIp.setDstIp(address1.toString()); + dstIp.setDstIpMask(network.getNetmask().asAddress().toString()); + } else { + dstIp.setDstIp("::"); + dstIp.setDstIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); + } + + ipConvertList.add(dstIp); + } else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + } else { + if (srcIp.getSrcIpAddress() != null) { + if (srcIp.getSrcIpAddress().indexOf("/") != -1) { + if (srcIp.getIpType() == 4 /* || srcIp.getIpType()==46 */) {// 46表示源ip为ipv4,目的ip为ipv6 + Integer srcMaskNum = Integer.parseInt(srcIp.getSrcIpAddress().split("/")[1]); + if (srcMaskNum == 0) { + dstIp.setSrcIpMask("0.0.0.0"); + } else { + dstIp.setSrcIpMask(IpUtil.convertMask(srcMaskNum)); + } + + dstIp.setSrcIp(srcIp.getSrcIpAddress().split("/")[0]); + } else if (srcIp.getIpType() == 6/* || srcIp.getIpType()==64 */) {// 64表示源ip为ipv6,目的ip为ipv4 + IPv6Network strangeNetwork = IPv6Network.fromString(srcIp.getSrcIpAddress()); + dstIp.setSrcIp(srcIp.getSrcIpAddress().split("/")[0]); + dstIp.setSrcIpMask(strangeNetwork.getNetmask().asAddress().toString()); + } /* + * else { Pattern + * patternV4Subnet=Pattern.compile(Constants.IPV4_IP_SUBNET_REGEXP); Pattern + * patternV6Subnet=Pattern.compile(Constants.IPV6_IP_SUBNET_REGEXP); Matcher + * matchernV4Subnet=patternV4Subnet.matcher(srcIp.getSrcIpAddress()); Matcher + * matcherV6Subnet=patternV6Subnet.matcher(srcIp.getSrcIpAddress()); + * if(matchernV4Subnet.matches()) { Integer srcMaskNum = + * Integer.parseInt(srcIp.getSrcIpAddress().split("/")[1]); if(srcMaskNum==0){ + * dstIp.setSrcIpMask("0.0.0.0"); }else{ + * dstIp.setSrcIpMask(IpUtil.convertMask(srcMaskNum)); } + * dstIp.setSrcIp(srcIp.getSrcIpAddress().split("/")[0]); }else + * if(matcherV6Subnet.matches()){ IPv6Network strangeNetwork = + * IPv6Network.fromString(srcIp.getSrcIpAddress()); + * dstIp.setSrcIp(srcIp.getSrcIpAddress().split("/")[0]); + * dstIp.setSrcIpMask(strangeNetwork.getNetmask().asAddress().toString()); }else + * { throw new RuntimeException("Invalid IP/subnet mask format"); } } + */ + else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + } else { + if (srcIp.getIpType() == 4/* || srcIp.getIpType()==46 */) {// 46表示源ip为ipv4,目的ip为ipv6 + dstIp.setSrcIp(srcIp.getSrcIpAddress()); + dstIp.setSrcIpMask("255.255.255.255"); + } else if (srcIp.getIpType() == 6/* || srcIp.getIpType()==64 */) {// 64表示源ip为ipv6,目的ip为ipv4 + dstIp.setSrcIp(srcIp.getSrcIpAddress()); + dstIp.setSrcIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); + } /* + * else {//all Pattern patternV4=Pattern.compile(Constants.IPV4_IP_REGEXP); + * Pattern patternV6=Pattern.compile(Constants.IPV6_IP_REGEXP); Matcher + * matcherV4=patternV4.matcher(srcIp.getSrcIpAddress()); Matcher + * matcherV6=patternV6.matcher(srcIp.getSrcIpAddress()); if(matcherV4.matches()) + * { dstIp.setSrcIp(srcIp.getSrcIpAddress()); + * dstIp.setSrcIpMask("255.255.255.255"); }else if(matcherV6.matches()) { + * dstIp.setSrcIp(srcIp.getSrcIpAddress()); + * dstIp.setSrcIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); }else { throw + * new RuntimeException("Invalid IP format"); } } + */ + else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + } + } else { + if (srcIp.getIpType() == 4/* || srcIp.getIpType()==46 */) {// 46表示源ip为ipv4,目的ip为ipv6 + dstIp.setSrcIp(srcIp.getSrcIpAddress()); + dstIp.setSrcIpMask("255.255.255.255"); + } else if (srcIp.getIpType() == 6/* || srcIp.getIpType()==64 */) {// 64表示源ip为ipv6,目的ip为ipv4 + dstIp.setSrcIp(srcIp.getSrcIpAddress()); + dstIp.setSrcIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); + } /* + * else {//all dstIp.setSrcIp(srcIp.getSrcIpAddress()); + * dstIp.setSrcIpMask("255.255.255.255"); } + */ + else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + } + if (srcIp.getDestIpAddress() != null) { + if (srcIp.getDestIpAddress().indexOf("/") != -1) { + if (srcIp.getIpType() == 4/* || srcIp.getIpType()==64 */) {// 64表示源ip为ipv6,目的ip为ipv4 + Integer dstMaskNum = Integer.parseInt(srcIp.getDestIpAddress().split("/")[1]); + if (dstMaskNum == 0) { + dstIp.setDstIpMask("0.0.0.0"); + } else { + dstIp.setDstIpMask(IpUtil.convertMask(dstMaskNum)); + ; + } + dstIp.setDstIp(srcIp.getDestIpAddress().split("/")[0]); + } else if (srcIp.getIpType() == 6/* || srcIp.getIpType()==46 */) {// 46表示源ip为ipv4,目的ip为ipv6 + IPv6Network strangeNetwork = IPv6Network.fromString(srcIp.getDestIpAddress()); + dstIp.setDstIp(srcIp.getDestIpAddress().split("/")[0]); + dstIp.setDstIpMask(strangeNetwork.getNetmask().asAddress().toString()); + } /* + * else { Pattern + * patternV4Subnet=Pattern.compile(Constants.IPV4_IP_SUBNET_REGEXP); Pattern + * patternV6Subnet=Pattern.compile(Constants.IPV6_IP_SUBNET_REGEXP); Matcher + * matchernV4Subnet=patternV4Subnet.matcher(srcIp.getDestIpAddress()); Matcher + * matcherV6Subnet=patternV6Subnet.matcher(srcIp.getDestIpAddress()); + * if(matchernV4Subnet.matches()) { Integer dstMaskNum = + * Integer.parseInt(srcIp.getDestIpAddress().split("/")[1]); if(dstMaskNum==0){ + * dstIp.setDstIpMask("0.0.0.0"); }else{ + * dstIp.setDstIpMask(IpUtil.convertMask(dstMaskNum));; } + * dstIp.setDstIp(srcIp.getDestIpAddress().split("/")[0]); }else + * if(matcherV6Subnet.matches()){ IPv6Network strangeNetwork = + * IPv6Network.fromString(srcIp.getDestIpAddress()); + * dstIp.setDstIp(srcIp.getDestIpAddress().split("/")[0]); + * dstIp.setDstIpMask(strangeNetwork.getNetmask().asAddress().toString()); }else + * { throw new RuntimeException("Invalid IP/subnet mask format"); } } + */ + else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + + } else { + if (srcIp.getIpType() == 4/* || srcIp.getIpType()==64 */) {// 64表示源ip为ipv6,目的ip为ipv4 + dstIp.setDstIp(srcIp.getDestIpAddress()); + dstIp.setDstIpMask("255.255.255.255"); + } else if (srcIp.getIpType() == 6/* || srcIp.getIpType()==46 */) {// 46表示源ip为ipv4,目的ip为ipv6 + dstIp.setDstIp(srcIp.getDestIpAddress()); + dstIp.setDstIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); + } /* + * else {//all Pattern patternV4=Pattern.compile(Constants.IPV4_IP_REGEXP); + * Pattern patternV6=Pattern.compile(Constants.IPV6_IP_REGEXP); Matcher + * matcherV4=patternV4.matcher(srcIp.getDestIpAddress()); Matcher + * matcherV6=patternV6.matcher(srcIp.getDestIpAddress()); + * if(matcherV4.matches()) { dstIp.setDstIp(srcIp.getDestIpAddress()); + * dstIp.setDstIpMask("255.255.255.255"); }else if(matcherV6.matches()) { + * dstIp.setDstIp(srcIp.getDestIpAddress()); + * dstIp.setDstIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); }else { throw + * new RuntimeException("invalid ip format"); } } + */ + else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + } + } else { + if (srcIp.getIpType() == 4/* || srcIp.getIpType()==64 */) {// 64表示源ip为ipv6,目的ip为ipv4 + dstIp.setDstIp(srcIp.getDestIpAddress()); + dstIp.setDstIpMask("255.255.255.255"); + } else if (srcIp.getIpType() == 6/* || srcIp.getIpType()==46 */) {// 46表示源ip为ipv4,目的ip为ipv6 + dstIp.setDstIp(srcIp.getDestIpAddress()); + dstIp.setDstIpMask("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"); + } /* + * else {//all dstIp.setDstIp(srcIp.getDestIpAddress()); + * dstIp.setDstIpMask("255.255.255.255"); } + */ + else { + throw new RuntimeException("Unsupported IP type " + srcIp.getIpType()); + } + } + if (srcIp.getSrcPort() != null) { + if (srcIp.getSrcPort().indexOf("/") != -1) { + String srcMaskNum = srcIp.getSrcPort().split("/")[1]; + dstIp.setSrcPortMask(srcMaskNum); + dstIp.setSrcPort(srcIp.getSrcPort().split("/")[0]); + } else { + dstIp.setSrcPort(srcIp.getSrcPort()); + dstIp.setSrcPortMask("65535"); + } + } else { + dstIp.setSrcPort("0"); + dstIp.setSrcPortMask("65535"); + } + if (srcIp.getDestPort() != null) { + if (srcIp.getDestPort().indexOf("/") != -1) { + String dstMaskNum = srcIp.getDestPort().split("/")[1]; + dstIp.setDstPortMask(dstMaskNum); + dstIp.setDstPort(srcIp.getDestPort().split("/")[0]); + } else { + dstIp.setDstPort(srcIp.getDestPort()); + dstIp.setDstPortMask("65535"); + } + } else { + dstIp.setDstPort("0"); + dstIp.setDstPortMask("65535"); + } + ipConvertList.add(dstIp); + } + return ipConvertList; + } + /** + * 设置端口值 + * + * @param dstIp + * @param srcIp + */ + public static void convertPortValues(IpCfg dstIp, BaseIpCfg srcIp) { + if (srcIp.getSrcPort() != null) { + if (srcIp.getSrcPort().indexOf("/") != -1) { + String srcMaskNum = srcIp.getSrcPort().split("/")[1]; + dstIp.setSrcPortMask(srcMaskNum); + dstIp.setSrcPort(srcIp.getSrcPort().split("/")[0]); + } else { + dstIp.setSrcPort(srcIp.getSrcPort()); + dstIp.setSrcPortMask("65535"); + } + } else { + dstIp.setSrcPort("0"); + dstIp.setSrcPortMask("65535"); + } + if (srcIp.getDestPort() != null) { + if (srcIp.getDestPort().indexOf("/") != -1) { + String dstMaskNum = srcIp.getDestPort().split("/")[1]; + dstIp.setDstPortMask(dstMaskNum); + dstIp.setDstPort(srcIp.getDestPort().split("/")[0]); + } else { + dstIp.setDstPort(srcIp.getDestPort()); + dstIp.setDstPortMask("65535"); + } + } else { + dstIp.setDstPort("0"); + dstIp.setDstPortMask("65535"); + } + } +} diff --git a/src/main/java/com/nis/util/Constants.java b/src/main/java/com/nis/util/Constants.java index 16aa98e50..177a8944f 100644 --- a/src/main/java/com/nis/util/Constants.java +++ b/src/main/java/com/nis/util/Constants.java @@ -814,4 +814,12 @@ public final class Constants { * 流量日志的HTTP泛收接口URL */ public static final String NTC_HTTP_RECORD_LOG = Configurations.getStringProperty("ntcHttpRecordLog",""); + /** + * 日期格式化 + */ + public static final String COMMON_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + /** + * 时间格式化 + */ + public static final String COMMON_TIME_FORMAT = "HH:mm:ss"; } diff --git a/src/main/java/com/nis/util/SchedulerTaskUtil.java b/src/main/java/com/nis/util/SchedulerTaskUtil.java index 52baa0ca0..b0050b138 100644 --- a/src/main/java/com/nis/util/SchedulerTaskUtil.java +++ b/src/main/java/com/nis/util/SchedulerTaskUtil.java @@ -1,24 +1,39 @@ package com.nis.util; +import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.config.IniSecurityManagerFactory; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import com.google.common.collect.Lists; +import com.nis.domain.basics.AsnIpCfg; +import com.nis.domain.callback.InlineIp; import com.nis.domain.configuration.AppPolicyCfg; import com.nis.domain.configuration.AvFileSampleCfg; import com.nis.domain.configuration.AvSignSampleCfg; import com.nis.domain.configuration.BaseCfg; +import com.nis.domain.configuration.BaseStringCfg; import com.nis.domain.configuration.CfgIndexInfo; +import com.nis.domain.configuration.ComplexkeywordCfg; +import com.nis.domain.configuration.DdosIpCfg; import com.nis.domain.configuration.DnsIpCfg; import com.nis.domain.configuration.DnsResStrategy; import com.nis.domain.configuration.FileDigestCfg; import com.nis.domain.configuration.IpPortCfg; import com.nis.domain.configuration.PxyObjKeyring; +import com.nis.domain.configuration.PxyObjSpoofingIpPool; import com.nis.domain.configuration.PxyObjTrustedCaCert; import com.nis.domain.configuration.PxyObjTrustedCaCrl; import com.nis.domain.maat.MaatCfg; @@ -32,8 +47,10 @@ import com.nis.domain.maat.MaatCfg.NumBoundaryCfg; import com.nis.domain.maat.MaatCfg.StringCfg; import com.nis.domain.maat.ToUpdateMaatBeanStatus.UpdateMaatCfgStatus; import com.nis.web.dao.configuration.ConfigSynchronizationDao; +import com.nis.web.security.UserUtils; import com.nis.web.service.BaseService; import com.nis.web.service.SpringContextHolder; +import com.nis.web.service.configuration.ConfigSynchronizationService; /** * 配置任务调度通用类 @@ -44,18 +61,26 @@ import com.nis.web.service.SpringContextHolder; public class SchedulerTaskUtil { //调度任务的配置信息,复用配置同步DAO - private static ConfigSynchronizationDao configSynchronizationDao = SpringContextHolder.getBean(ConfigSynchronizationDao.class); private Logger logger = LoggerFactory.getLogger(getClass()); /** * 根据业务与编译ID查询配置,修改失效或生效状态,并下发至综合服务 * @param serviceId 不可空 * @param compileId 不可空 - * @param oldIsValid 配置当前状态 0无效,1有效,可空 - * @param newIsValid 配置最新修改状态 0无效,1有效,不可空 + * @param isValid 配置生效状态:0停用,1启用 + * @param isIssueContent 是否下发内容:0不下发,1下发 * @return boolean + * @throws SecurityException + * @throws NoSuchFieldException + * @throws IllegalAccessException + * @throws IllegalArgumentException */ - public boolean updateConfigByServiceAndCompile(Integer serviceId,Integer compileId,Integer oldIsValid,Integer newIsValid){ + public boolean updateConfigByServiceAndCompile(Integer serviceId,Integer compileId,Integer isValid,Integer isIssueContent,ConfigSynchronizationDao configSynchronizationDao) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{ +// SecurityManagerInit(); +// Subject subject = login("admin","zdjzsoft"); +// System.out.println(subject.getPrincipal()); +// System.out.println(subject.hasRole("role1")); +// System.out.println(subject.hasRole("Superman")); //根据业务查询配置文件,获取该业务的配置域表信息 ServiceConfigTemplateUtil serviceTemplate = new ServiceConfigTemplateUtil(); List> serviceList = serviceTemplate.getServiceListByServiceId(serviceId); @@ -67,271 +92,844 @@ public class SchedulerTaskUtil { BaseCfg entity = new BaseCfg(); entity.setServiceId(serviceId); entity.setTableName(tableName); - List list = Lists.newArrayList(); List callBackCfgList = Lists.newArrayList(); - boolean isUpdateContent = false; - /** - * 根据编译ID查询配置,如果配置当前审核状态为未审核(is_audit=0),并且newIsValid=1需要查询详细的域配置信息,下发配置详细内容, - * 如果已审核(is_audit=1),则只查询配置主表,更新配置状态即可, - * 如果审核取消(is_audit=3)则删除定时任务,表示配置已最终删除,此状态处理原则上在配置修改拦截器中处理 - */ + if("1".equals(serviceType)){//maat类配置 Date updateTime = new Date(); - //下发并修改配置状态的参数类 - ToUpdateMaatBeanStatus maatStatusBean = new ToUpdateMaatBeanStatus(); - UpdateMaatCfgStatus updateCfg = new UpdateMaatCfgStatus(); - List configCompileStartStopList = new ArrayList(); - maatStatusBean.setVersion(Constants.MAAT_VERSION); - maatStatusBean.setOpAction(Constants.INSERT_ACTION); - maatStatusBean.setAuditTime(updateTime); - maatStatusBean.setCreatorName("TaskScheduler");//任务调度定时修改状态 - - //下发带有配置内容的参数对象 - ToMaatBean maatBean = new ToMaatBean(); - MaatCfg maatCfg = new MaatCfg(); - List configCompileList = new ArrayList(); - List groupRelationList = new ArrayList(); - List ipRegionList = new ArrayList(); - List strRegionList = new ArrayList(); - List numRegionList = new ArrayList(); - List digestRegionList = new ArrayList(); - List areaIpRegionList = new ArrayList(); - -// for(Integer compileId:compileIds){ + ToMaatBean maatBean; + MaatCfg maatCfg; + maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + List configCompileList; + if(isIssueContent.equals(1)){ + //修改配置内容以及状态 +// ToMaatBean maatBean; +// MaatCfg maatCfg; +// List configCompileList; + List groupRelationList; + List ipRegionList; + List strRegionList; + List numRegionList; + List digestRegionList; + List areaIpRegionList; + + List ipList = new ArrayList(); + List asnIpList = new ArrayList(); + List strList = new ArrayList(); + List complexStrList = new ArrayList(); + List numList = new ArrayList(); + List fileList = new ArrayList(); + maatBean = new ToMaatBean(); + configCompileList = new ArrayList(); + List compileIds = new ArrayList(); + List asnGroupIds = new ArrayList(); + //获取业务下的配置域 + List> cfgList = (List>) service.get("cfgList"); + //获取业务下的自定义域 + List> userRegionList = (List>) service.get("userRegionList"); entity.setCompileId(compileId); + compileIds.add(compileId); //查询配置 if("cfg_index_info".equals(tableName)){ - list = configSynchronizationDao.getCfgIndexList(entity); - List> cfgList = (List>) service.get("cfgList"); - for(int i=0;i m:cfgList){ - String regionTableName = m.get("tableName").toString(); - config.setTableName(regionTableName); - configSynchronizationDao.updateCfgStatus(cfg);//修改界面数据库配置状态 + List list = configSynchronizationDao.getCfgIndexList(entity); + if(isIssueContent.equals(1)){ + //查询子域配置详情 + if(cfgList!=null){ + for(Map m:cfgList){ + String regionTable = m.get("tableName").toString(); + if("1".equals(m.get("cfgType"))){ + ipList.addAll(configSynchronizationDao.getIpPortList(regionTable, compileIds)); + }else if("2".equals(m.get("cfgType"))){ + strList.addAll(configSynchronizationDao.getStrList(regionTable,compileIds)); + }else if("3".equals(m.get("cfgType"))){ + complexStrList.addAll(configSynchronizationDao.getComplexStrList(regionTable,compileIds)); + }else if("4".equals(m.get("cfgType"))){ + + }else if("5".equals(m.get("cfgType"))){ + fileList.addAll(configSynchronizationDao.getFileDigestList(regionTable, compileIds)); } } } - } - }else if("file_digest_cfg".equals(tableName)){ - list = configSynchronizationDao.getFileDigestListByService(entity); - List> cfgList = (List>) service.get("cfgList"); - for(int i=0;i m:cfgList){ - String regionTableName = m.get("tableName").toString(); - config.setTableName(regionTableName); - configSynchronizationDao.updateCfgStatus(cfg);//修改界面数据库配置状态 + //批量获取regionId,groupId(相同编译下的IP类配置多条ip只获取一个组号),分组复用的域配置不需要重新获取regionId,groupId + List regionIds = ConfigServiceUtil.getId(3, ipList.size()+strList.size()+complexStrList.size()+numList.size()+fileList.size()); + List groupIds = ConfigServiceUtil.getId(2, ipList.size()+strList.size()+complexStrList.size()+numList.size()+fileList.size()); + entity.setIsValid(isValid);//将最新的配置状态赋给配置对象 + entity.setAuditTime(updateTime); + for(CfgIndexInfo cfg:list){ + groupRelationList = new ArrayList(); + ipRegionList = new ArrayList(); + strRegionList = new ArrayList(); + numRegionList = new ArrayList(); + digestRegionList = new ArrayList(); + areaIpRegionList = new ArrayList(); + List list1 = new ArrayList(); + List list2 = new ArrayList(); + List list3 = new ArrayList(); + List list4 = new ArrayList(); + List list5 = new ArrayList(); + String userRegion = ""; + //处理自定义域 + if(userRegionList!=null){ + for(Map n:userRegionList){ + Object userRegionPosition = n.get("userRegionPosition"); + if(userRegionPosition!=null && (userRegionPosition.toString().equals("1")||userRegionPosition.toString().equals("0"))){ + //通过反射机制获取自定义域字段值 + String regionColumn = n.get("regionColumn").toString(); + Class aClass = null; + if(userRegionPosition.toString().equals(("0"))){ + aClass = BaseCfg.class; + }else{ + aClass = CfgIndexInfo.class; + } + + Object value = ""; + if(entity.getServiceId().equals(517)||entity.getServiceId().equals(560)){//代理替换策略 + String[] regionArray = regionColumn.split(","); + for(int r=0;r> cfgList = (List>) service.get("cfgList"); - for(int i=0;i m:cfgList){ - String regionTableName = m.get("tableName").toString(); - config.setTableName(regionTableName); - configSynchronizationDao.updateCfgStatus(cfg);//修改界面数据库配置状态 + for(AsnIpCfg ip:asnIpList){//asn不需要再次获取regionId,groupId + if(ip.getAsnIpGroup().toString().equals(cfg.getUserRegion4())){//根据组号对应 + ip.setIsValid(entity.getIsValid()); + ip.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + list1.add(ip); } } + //ip spoofing + if(cfg.getServiceId().equals(518)){ + //IP仿冒策略 + //仿冒IP池配置匹配下发或者取消 + PxyObjSpoofingIpPool pool=new PxyObjSpoofingIpPool(); + pool.setCfgId(Long.valueOf(cfg.getUserRegion3())); +// pxyObjSpoofingIpPoolDao.update(pool); + pool = configSynchronizationDao.getPxyObjSpoofingIpPool(pool.getCfgId()); + pool.setIsValid(entity.getIsValid()); + pool.setIsAudit(entity.getIsAudit()); + pool.setAuditorId(entity.getAuditorId()); + pool.setAuditTime(entity.getAuditTime()); + List poolList = new ArrayList(); + String json=""; + String areaEffectiveIds="0"; + if(isValid==1){ + pool.setAreaEffectiveIds(areaEffectiveIds); + pool.setGroupId(pool.getCfgId().intValue());//界面端的配置ID作为策略分组ID + poolList.add(pool); + //调用服务接口下发配置数据 + json=BaseService.gsonToJson(poolList); + logger.info("欺骗IP池配置下发配置参数:"+json); + //调用服务接口下发配置 + try { + ToMaatResult result = ConfigServiceUtil.postCallbackCfg(json); + if(result!=null){ + logger.info("欺骗IP池配置下发响应信息:"+result.getMsg()); + } + } catch (Exception e) { + logger.error("欺骗IP池配置配置下发失败",e); + throw e; + } + } + } + if(list1.size()>0){ + GroupCfg groupCfg=new GroupCfg(); + groupCfg.setCompileId(cfg.getCompileId()); + groupCfg.setGroupId(Integer.parseInt(cfg.getUserRegion4())); + groupCfg.setIsValid(entity.getIsValid()); + groupCfg.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + groupRelationList.add(groupCfg); + ipRegionList.addAll(ConfigConvertUtil.groupReuseCfgAddRemoveConvert(list1,Constants.VALID_YES,null)); + }else if(!StringUtil.isEmpty(asnGroupIds)) { + GroupCfg groupCfg=new GroupCfg(); + groupCfg.setCompileId(cfg.getCompileId()); + groupCfg.setGroupId(Integer.parseInt(cfg.getUserRegion4())); + groupCfg.setIsValid(entity.getIsValid()); + groupCfg.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + groupRelationList.add(groupCfg); + ipRegionList.addAll(ipRegionList); + } + //配置域转换 + userRegion = ConfigConvertUtil.configCovert(ipList,strList,complexStrList, + numList,fileList,regionIds,groupIds,entity,cfg.getCompileId(), + StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime(), + groupRelationList,ipRegionList,strRegionList,numRegionList,digestRegionList,areaIpRegionList,userRegion); + BeanUtils.copyProperties(cfg, maatCfg); + maatCfg.setAction(cfg.getAction()); + maatCfg.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + maatCfg.setIpRegionList(ipRegionList); + maatCfg.setStrRegionList(strRegionList); + maatCfg.setNumRegionList(numRegionList); + maatCfg.setDigestRegionList(digestRegionList); + maatCfg.setGroupRelationList(groupRelationList); + maatCfg.setGroupNum(groupRelationList.size()); + maatCfg.setAreaIpRegionList(areaIpRegionList); + maatCfg.setIsValid(entity.getIsValid()); + if(!StringUtil.isEmpty(userRegion)){ + maatCfg.setUserRegion(userRegion); + } + configCompileList.add(maatCfg); + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(new Date()); + maatBean.setCreatorName("TaskScheduler"); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.INSERT_ACTION); + String json=BaseService.gsonToJson(maatBean); + logger.info("定时任务修改NTC/PROXY策略的MAAT配置内容:"+json); + //调用服务接口修改配置内容与状态 + ToMaatResult result = ConfigServiceUtil.postMaatCfg(json); + if(result!=null){ + logger.info("定时任务修改NTC/PROXY策略的MAAT配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + } + }else{ + /*maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + maatBean = new ToMaatBean(); + configCompileList = new ArrayList(); + for(CfgIndexInfo cfg:list){ + if(StringUtils.isNotEmpty(cfg.getCommonGroupIds())){ + maatCfg.setKeepGroupList(Arrays.asList(cfg.getCommonGroupIds().split(","))); + } + maatCfg.setCompileId(compileId); + maatCfg.setServiceId(serviceId); + maatCfg.setIsValid(isValid);//配置状态 + configCompileList.add(maatCfg); + + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(entity.getAuditTime()); + maatBean.setCreatorName(entity.getCurrentUser().getName()); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.UPDATE_ACTION); + //调用服务接口取消配置 + String json=BaseService.gsonToJson(maatBean); + logger.info("定时器修改配置状态:"+json); + //调用服务接口下发配置 + ToMaatResult result = ConfigServiceUtil.put(json,1); + logger.info("定时器修改配置状态响应时间:"+result.getMsg()); + if(result!=null){ + logger.info("定时任务修改NTC/PROXY策略的MAAT配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + }*/ + } + + }else if("ddos_ip_cfg".equals(tableName)){ + List list = configSynchronizationDao.getDdosIpCfgList(entity); + if(isIssueContent.equals(1)){ + //查询子域配置详情 + if(cfgList!=null){ + for(Map m:cfgList){ + String regionTable = m.get("tableName").toString(); + if("1".equals(m.get("cfgType"))){ + ipList.addAll(configSynchronizationDao.getIpPortList(regionTable, compileIds)); + }else if("2".equals(m.get("cfgType"))){ + strList.addAll(configSynchronizationDao.getStrList(regionTable,compileIds)); + }else if("3".equals(m.get("cfgType"))){ + complexStrList.addAll(configSynchronizationDao.getComplexStrList(regionTable,compileIds)); + }else if("4".equals(m.get("cfgType"))){ + + }else if("5".equals(m.get("cfgType"))){ + fileList.addAll(configSynchronizationDao.getFileDigestList(regionTable, compileIds)); + } + } + } + //批量获取regionId,groupId(相同编译下的IP类配置多条ip只获取一个组号),分组复用的域配置不需要重新获取regionId,groupId + List regionIds = ConfigServiceUtil.getId(3, ipList.size()+strList.size()+complexStrList.size()+numList.size()+fileList.size()); + List groupIds = ConfigServiceUtil.getId(2, ipList.size()+strList.size()+complexStrList.size()+numList.size()+fileList.size()); + entity.setIsValid(isValid);//将最新的配置状态赋给配置对象 + entity.setAuditTime(updateTime); + for(int i=0;i list1 = new ArrayList(); + String userRegion = ""; + //处理自定义域 + if(userRegionList!=null){ + for(Map n:userRegionList){ + Object userRegionPosition = n.get("userRegionPosition"); + if(userRegionPosition!=null && (userRegionPosition.toString().equals("1")||userRegionPosition.toString().equals("0"))){ + //通过反射机制获取自定义域字段值 + String regionColumn = n.get("regionColumn").toString(); + Class aClass = null; + if(userRegionPosition.toString().equals(("0"))){ + aClass = BaseCfg.class; + }else{ + aClass = DdosIpCfg.class; + } + Object value = ""; + Field field = aClass.getDeclaredField(regionColumn); + field.setAccessible(true); + value = field.get(cfg); + if(!StringUtil.isEmpty(value)){ + if(StringUtil.isEmpty(n.get("regionKey"))){ + userRegion = value.toString(); + }else{ + userRegion += n.get("regionKey")+"="+value+Constants.USER_REGION_SPLIT; + } + } + } + } + if(userRegion.endsWith(Constants.USER_REGION_SPLIT)){ + userRegion = userRegion.substring(0, userRegion.length()-1); + } + } + list1.add(cfg); + if(list1.size()>0){ + Map map = ConfigConvertUtil.cfgToMaatConvert(ipRegionList,list1,1,groupRelationList); + groupRelationList=map.get("groupList"); + ipRegionList=map.get("dstList"); + if(map.get("numRegionList")!=null){ + numRegionList.addAll(map.get("numRegionList")); + } + } + BeanUtils.copyProperties(cfg, maatCfg); + maatCfg.setAction(cfg.getAction()); + maatCfg.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + maatCfg.setIpRegionList(ipRegionList); + maatCfg.setStrRegionList(strRegionList); + maatCfg.setNumRegionList(numRegionList); + maatCfg.setDigestRegionList(digestRegionList); + maatCfg.setGroupRelationList(groupRelationList); + maatCfg.setGroupNum(groupRelationList.size()); + maatCfg.setAreaIpRegionList(areaIpRegionList); + maatCfg.setIsValid(entity.getIsValid()); + if(!StringUtil.isEmpty(userRegion)){ + maatCfg.setUserRegion(userRegion); + } + configCompileList.add(maatCfg); + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(new Date()); + maatBean.setCreatorName("TaskScheduler"); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.INSERT_ACTION); + String json=BaseService.gsonToJson(maatBean); + logger.info("定时任务修改DDOS配置内容:"+json); + //调用服务接口修改配置内容与状态 + ToMaatResult result = ConfigServiceUtil.postMaatCfg(json); + if(result!=null){ + logger.info("定时任务修改DDOS配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + } + }else{ + /*maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + maatBean = new ToMaatBean(); + configCompileList = new ArrayList(); + for(CfgIndexInfo cfg:list){ + if(StringUtils.isNotEmpty(cfg.getCommonGroupIds())){ + maatCfg.setKeepGroupList(Arrays.asList(cfg.getCommonGroupIds().split(","))); + } + maatCfg.setCompileId(compileId); + maatCfg.setServiceId(serviceId); + maatCfg.setIsValid(isValid);//配置状态 + configCompileList.add(maatCfg); + + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(entity.getAuditTime()); + maatBean.setCreatorName(entity.getCurrentUser().getName()); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.UPDATE_ACTION); + //调用服务接口取消配置 + String json=BaseService.gsonToJson(maatBean); + logger.info("定时器修改配置状态:"+json); + //调用服务接口下发配置 + ToMaatResult result = ConfigServiceUtil.put(json,1); + logger.info("定时器修改配置状态响应时间:"+result.getMsg()); + if(result!=null){ + logger.info("定时任务修改NTC/PROXY策略的MAAT配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + }*/ + } + + }else if("file_digest_cfg".equals(tableName)){ + List list = configSynchronizationDao.getFileDigestListByService(entity); + if(isIssueContent.equals(1)){ + if(cfgList!=null){ + for(Map m:cfgList){ + String regionTable = m.get("tableName").toString(); + if("1".equals(m.get("cfgType"))){ + ipList.addAll(configSynchronizationDao.getIpPortList(regionTable, compileIds)); + }else if("2".equals(m.get("cfgType"))){ + strList.addAll(configSynchronizationDao.getStrList(regionTable,compileIds)); + }else if("3".equals(m.get("cfgType"))){ + complexStrList.addAll(configSynchronizationDao.getComplexStrList(regionTable,compileIds)); + }else if("4".equals(m.get("cfgType"))){ + + }else if("5".equals(m.get("cfgType"))){ + fileList.addAll(configSynchronizationDao.getFileDigestList(regionTable, compileIds)); + } + } + } + //批量获取regionId,groupId(相同编译下的IP类配置多条ip只获取一个组号),分组复用的域配置不需要重新获取regionId,groupId + List regionIds = ConfigServiceUtil.getId(3, ipList.size()+strList.size()+complexStrList.size()+numList.size()+fileList.size()); + List groupIds = ConfigServiceUtil.getId(2, ipList.size()+strList.size()+complexStrList.size()+numList.size()+fileList.size()); + entity.setIsValid(isValid);//将最新的配置状态赋给配置对象 + entity.setAuditTime(updateTime); + for(FileDigestCfg cfg:list){ + maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + groupRelationList = new ArrayList(); + ipRegionList = new ArrayList(); + strRegionList = new ArrayList(); + numRegionList = new ArrayList(); + digestRegionList = new ArrayList(); + areaIpRegionList = new ArrayList(); + List list1 = new ArrayList(); + List list2 = new ArrayList(); + List list3 = new ArrayList(); + List list4 = new ArrayList(); + List list5 = new ArrayList(); + String userRegion = ""; + //处理自定义域 + if(userRegionList!=null){ + for(Map n:userRegionList){ + Object userRegionPosition = n.get("userRegionPosition"); + if(userRegionPosition!=null && (userRegionPosition.toString().equals("1")||userRegionPosition.toString().equals("0"))){ + //通过反射机制获取自定义域字段值 + String regionColumn = n.get("regionColumn").toString(); + Class aClass = null; + if(userRegionPosition.toString().equals(("0"))){ + aClass = BaseCfg.class; + }else{ + aClass = FileDigestCfg.class; + } + Object value = ""; + Field field = aClass.getDeclaredField(regionColumn); + field.setAccessible(true); + value = field.get(cfg); + if(!StringUtil.isEmpty(value)){ + if(StringUtil.isEmpty(n.get("regionKey"))){ + userRegion = value.toString(); + }else{ + userRegion += n.get("regionKey")+"="+value+Constants.USER_REGION_SPLIT; + } + } + } +// System.out.println("userRegionList:"+n.get("regionKey")+","+n.get("regionColumn")+","+n.get("handleType")); + } + if(userRegion.endsWith(Constants.USER_REGION_SPLIT)){ + userRegion = userRegion.substring(0, userRegion.length()-1); + } + } + //配置域转换 + ConfigConvertUtil.configCovert(ipList,strList,complexStrList, + numList,fileList,regionIds,groupIds,entity,cfg.getCompileId(), + StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime(), + groupRelationList,ipRegionList,strRegionList,numRegionList,digestRegionList,areaIpRegionList,userRegion); + BeanUtils.copyProperties(cfg, maatCfg); + maatCfg.setAction(cfg.getAction()); + maatCfg.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + maatCfg.setIpRegionList(ipRegionList); + maatCfg.setStrRegionList(strRegionList); + maatCfg.setNumRegionList(numRegionList); + maatCfg.setDigestRegionList(digestRegionList); + maatCfg.setGroupRelationList(groupRelationList); + maatCfg.setGroupNum(groupRelationList.size()); + maatCfg.setAreaIpRegionList(areaIpRegionList); + maatCfg.setIsValid(entity.getIsValid()); + if(!StringUtil.isEmpty(userRegion)){ + maatCfg.setUserRegion(userRegion); + } + configCompileList.add(maatCfg); + } + + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(new Date()); + maatBean.setCreatorName("TaskScheduler"); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.INSERT_ACTION); + String json=BaseService.gsonToJson(maatBean); + logger.info("定时任务下发文件摘要配置内容:"+json); + //调用服务接口更新配置 + ToMaatResult result = ConfigServiceUtil.postMaatCfg(json); + if(result!=null){ + logger.info("定时任务修改文件摘要类配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + } + }else{ + /*maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + maatBean = new ToMaatBean(); + configCompileList = new ArrayList(); + for(FileDigestCfg cfg:list){ + if(StringUtils.isNotEmpty(cfg.getCommonGroupIds())){ + maatCfg.setKeepGroupList(Arrays.asList(cfg.getCommonGroupIds().split(","))); + } + maatCfg.setCompileId(compileId); + maatCfg.setServiceId(serviceId); + maatCfg.setIsValid(isValid);//配置状态 + configCompileList.add(maatCfg); + + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(entity.getAuditTime()); + maatBean.setCreatorName(entity.getCurrentUser().getName()); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.UPDATE_ACTION); + //调用服务接口取消配置 + String json=BaseService.gsonToJson(maatBean); + logger.info("定时器修改配置状态:"+json); + //调用服务接口下发配置 + ToMaatResult result = ConfigServiceUtil.put(json,1); + logger.info("定时器修改配置状态响应时间:"+result.getMsg()); + if(result!=null){ + logger.info("定时任务修改NTC/PROXY策略的MAAT配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + }*/ + } + + + }else if("app_policy_cfg".equals(tableName)){ + List list = configSynchronizationDao.getAppPolicyList(entity); + if(isIssueContent.equals(1)){ + if(cfgList!=null){ + for(Map m:cfgList){ + String regionTable = m.get("tableName").toString(); + if("1".equals(m.get("cfgType"))){ + ipList.addAll(configSynchronizationDao.getIpPortList(regionTable, compileIds)); + }else if("2".equals(m.get("cfgType"))){ + strList.addAll(configSynchronizationDao.getStrList(regionTable,compileIds)); + }else if("3".equals(m.get("cfgType"))){ + complexStrList.addAll(configSynchronizationDao.getComplexStrList(regionTable,compileIds)); + }else if("4".equals(m.get("cfgType"))){ + + }else if("5".equals(m.get("cfgType"))){ + fileList.addAll(configSynchronizationDao.getFileDigestList(regionTable, compileIds)); + } + } + } + //批量获取regionId,groupId(相同编译下的IP类配置多条ip只获取一个组号),compileIds.size()表示app策略本身有一个字符串域 + List regionIds = ConfigServiceUtil.getId(3, ipList.size()+strList.size()+compileIds.size()+complexStrList.size()+numList.size()+fileList.size()); + List groupIds = ConfigServiceUtil.getId(2, ipList.size()+strList.size()+compileIds.size()+complexStrList.size()+numList.size()+fileList.size()); + entity.setIsValid(isValid);//将最新的配置状态赋给配置对象 + entity.setAuditTime(updateTime); + for(AppPolicyCfg cfg:list){ + maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + groupRelationList = new ArrayList(); + ipRegionList = new ArrayList(); + strRegionList = new ArrayList(); + numRegionList = new ArrayList(); + digestRegionList = new ArrayList(); + areaIpRegionList = new ArrayList(); + List list1 = new ArrayList(); + List list2 = new ArrayList(); + List list3 = new ArrayList(); + List list4 = new ArrayList(); + List list5 = new ArrayList(); + String userRegion = ""; + //处理自定义域 + if(userRegionList!=null){ + for(Map n:userRegionList){ + Object userRegionPosition = n.get("userRegionPosition"); + if(userRegionPosition!=null && (userRegionPosition.toString().equals("1")||userRegionPosition.toString().equals("0"))){ + //通过反射机制获取自定义域字段值 + String regionColumn = n.get("regionColumn").toString(); + Class aClass = null; + if(userRegionPosition.toString().equals(("0"))){ + aClass = BaseCfg.class; + }else{ + aClass = AppPolicyCfg.class; + } + Object value = ""; + Field field = aClass.getDeclaredField(regionColumn); + field.setAccessible(true); + value = field.get(cfg); + if(!StringUtil.isEmpty(value)){ + if(StringUtil.isEmpty(n.get("regionKey"))){ + userRegion = value.toString(); + }else{ + userRegion += n.get("regionKey")+"="+value+Constants.USER_REGION_SPLIT; + } + } + } + } + if(userRegion.endsWith(Constants.USER_REGION_SPLIT)){ + userRegion = userRegion.substring(0, userRegion.length()-1); + } + } + //将app码与行为码设置为字符串域 + StringBuffer cfgKeywords = new StringBuffer(); + BaseStringCfg strCfg = new BaseStringCfg(); + if(cfg.getServiceId().equals(35)||cfg.getServiceId().equals(147)||cfg.getServiceId().equals(1059)){//基础协议 + cfgKeywords.append(Constants.PROTO_ID_REGION + "=" + cfg.getAppCode()); + }else if(cfg.getServiceId().equals(33)||cfg.getServiceId().equals(145)||cfg.getServiceId().equals(1056)){ + cfgKeywords.append(Constants.APP_ID_REGION + "=" + cfg.getAppCode()); + if(cfg.getBehavCode()!=null){ + cfgKeywords.append(Constants.KEYWORD_EXPR); + cfgKeywords.append(Constants.BEHAV_ID_REGION + "=" + cfg.getBehavCode()); + } + }else if(cfg.getServiceId().equals(36)||cfg.getServiceId().equals(148)||cfg.getServiceId().equals(1060)){//隧道加密协议 + cfgKeywords.append(Constants.PROTO_ID_REGION + "=" + cfg.getAppCode()); + if(cfg.getBehavCode()!=null){ + cfgKeywords.append(Constants.KEYWORD_EXPR); + cfgKeywords.append(Constants.BEHAV_ID_REGION + "=" + cfg.getBehavCode()); + } + } + cfg.setCfgKeywords(cfgKeywords.toString()); + BeanUtils.copyProperties(cfg, strCfg,new String[]{"menuNameCode"}); + strList.add(strCfg); + //配置域转换 + ConfigConvertUtil.configCovert(ipList,strList,complexStrList, + numList,fileList,regionIds,groupIds,entity,cfg.getCompileId(), + StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime(), + groupRelationList,ipRegionList,strRegionList,numRegionList,digestRegionList,areaIpRegionList,userRegion); + + BeanUtils.copyProperties(cfg, maatCfg); + maatCfg.setAction(cfg.getAction()); + maatCfg.setAuditTime(StringUtil.isEmpty(entity.getAuditTime()) ? cfg.getAuditTime():entity.getAuditTime()); + maatCfg.setIpRegionList(ipRegionList); + maatCfg.setStrRegionList(strRegionList); + maatCfg.setNumRegionList(numRegionList); + maatCfg.setDigestRegionList(digestRegionList); + maatCfg.setGroupRelationList(groupRelationList); + maatCfg.setGroupNum(groupRelationList.size()); + maatCfg.setAreaIpRegionList(areaIpRegionList); + maatCfg.setIsValid(entity.getIsValid()); + if(!StringUtil.isEmpty(userRegion)){ + maatCfg.setUserRegion(userRegion); + } + configCompileList.add(maatCfg); + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(new Date()); + maatBean.setCreatorName("TaskScheduler"); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.INSERT_ACTION); + String json=BaseService.gsonToJson(maatBean); + logger.info("定时任务下发APP POLICY MAAT配置内容:"+json); + //调用服务接口下发配置数据 + ToMaatResult result = ConfigServiceUtil.postMaatCfg(json); + if(result!=null){ + logger.info("定时任务更新APP POLICY配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + } + }else{ + /*maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + maatBean = new ToMaatBean(); + configCompileList = new ArrayList(); + for(AppPolicyCfg cfg:list){ + if(StringUtils.isNotEmpty(cfg.getCommonGroupIds())){ + maatCfg.setKeepGroupList(Arrays.asList(cfg.getCommonGroupIds().split(","))); + } + maatCfg.setCompileId(compileId); + maatCfg.setServiceId(serviceId); + maatCfg.setIsValid(isValid);//配置状态 + configCompileList.add(maatCfg); + + } + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(entity.getAuditTime()); + maatBean.setCreatorName(entity.getCurrentUser().getName()); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.UPDATE_ACTION); + //调用服务接口取消配置 + String json=BaseService.gsonToJson(maatBean); + logger.info("定时器修改配置状态:"+json); + //调用服务接口下发配置 + ToMaatResult result = ConfigServiceUtil.put(json,1); + logger.info("定时器修改配置状态响应时间:"+result.getMsg()); + if(result!=null){ + logger.info("定时任务修改NTC/PROXY策略的MAAT配置内容响应信息:"+result.getMsg()); + return true; + }else{ + return false; + }*/ + } + + } + + }else{//只修改配置状态 + //下发并修改配置状态的参数类 + ToUpdateMaatBeanStatus maatStatusBean = new ToUpdateMaatBeanStatus(); + UpdateMaatCfgStatus updateCfg = new UpdateMaatCfgStatus(); + List configCompileStartStopList = new ArrayList(); + maatStatusBean.setVersion(Constants.MAAT_VERSION); + maatStatusBean.setOpAction(Constants.UPDATE_ACTION); + maatStatusBean.setAuditTime(updateTime); + maatStatusBean.setCreatorName("TaskScheduler");//任务调度定时修改状态 + updateCfg.setIsValid(isValid); + updateCfg.setCompileId(compileId); + updateCfg.setAuditTime(updateTime); + updateCfg.setService(serviceId); + configCompileStartStopList.add(updateCfg); + maatStatusBean.setConfigCompileStartStopList(configCompileStartStopList); + + //ip spoofing + if(serviceId.equals(518)){ + entity.setCompileId(compileId); + List list = configSynchronizationDao.getCfgIndexList(entity); + for(CfgIndexInfo cfg:list){ + PxyObjSpoofingIpPool pool=new PxyObjSpoofingIpPool(); + pool.setCfgId(Long.valueOf(cfg.getUserRegion3())); + pool = configSynchronizationDao.getPxyObjSpoofingIpPool(pool.getCfgId()); + List poolList = new ArrayList(); + pool.setIsValid(0); + pool.setCompileId(pool.getCompileId()); + pool.setServiceId(pool.getServiceId()); + poolList.add(pool); + //调用服务接口取消配置 + String json=BaseService.gsonToJson(poolList); + logger.info("欺骗IP池配置配置参数:"+json); + //调用服务接口取消配置 + try { + ToMaatResult result = ConfigServiceUtil.put(json, 2); + logger.info("欺骗IP池配置响应信息:"+result.getMsg()); + } catch (Exception e) { + e.printStackTrace(); + logger.info("欺骗IP池配置配置失败"); + throw e; } } } - if(!isUpdateContent){ - updateCfg.setIsValid(newIsValid); - updateCfg.setCompileId(compileId); - updateCfg.setAuditTime(updateTime); - configCompileStartStopList.add(updateCfg); - } -// } - if(isUpdateContent){//修改配置内容以及状态 - //下发配置内容 - }else{//只修改配置状态 - maatStatusBean.setConfigCompileStartStopList(configCompileStartStopList); - String json=BaseService.gsonToJson(maatBean); + String json=BaseService.gsonToJson(maatStatusBean); + logger.info("MAAT类配置启停状态修改内容:"+json); //调用服务启停接口 String result = ConfigServiceUtil.configStatusUpdate(json); - logger.debug("MAAT类配置启停状态修改结果:"+result); + if(result!=null){ + logger.info("MAAT类配置启停状态修改结果:"+result); + }else{ + return false; + } + /*maatCfg = new MaatCfg(); + maatCfg.initDefaultValue(); + maatBean = new ToMaatBean(); + configCompileList = new ArrayList(); + maatCfg.setCompileId(compileId); + maatCfg.setServiceId(serviceId); + maatCfg.setIsValid(isValid);//配置状态 + configCompileList.add(maatCfg); + maatBean.setConfigCompileList(configCompileList); + maatBean.setAuditTime(entity.getAuditTime()); + maatBean.setCreatorName(entity.getCurrentUser().getName()); + maatBean.setVersion(Constants.MAAT_VERSION); + maatBean.setOpAction(Constants.UPDATE_ACTION); + //调用服务接口取消配置 + String json=BaseService.gsonToJson(maatBean); + logger.info("定时器修改配置状态:"+json); + //调用服务接口下发配置 + ToMaatResult result = ConfigServiceUtil.put(json,1); + logger.info("定时器修改配置状态响应时间:"+result.getMsg());*/ } }else if("2".equals(serviceType)){//回调类配置 List ids = Lists.newArrayList(); -// for(Integer compileId:compileIds){ + if(isIssueContent.equals(1)){//修改配置内容以及状态 entity.setCompileId(compileId); //查询配置 if(entity.getServiceId().equals(3)){//ip drop回调类配置用了主表和子表关系 - list = configSynchronizationDao.getCfgIndexList(entity); + List list = configSynchronizationDao.getCfgIndexList(entity); if(!StringUtil.isEmpty(list)){ List compileIdArray = Lists.newArrayList(); - for(int i=0;i list = configSynchronizationDao.getAvFileCfgList(entity); for(int i=0;i list = configSynchronizationDao.getIpPortListByService(entity); + Date updateTime = new Date(); for(int i=0;i factory = new IniSecurityManagerFactory("classpath:shiro.ini"); + //2.得道SecurityManager 实例,并绑定给SecurityUtils。 + SecurityManager securityManager = factory.getInstance(); + SecurityUtils.setSecurityManager(securityManager); + } + private Subject login(String username,String password) { + Subject subject = SecurityUtils.getSubject(); + UsernamePasswordToken token = new UsernamePasswordToken(username, password); + subject.login(token); + return subject; + } public static void main(String[] args) { - + } } diff --git a/src/main/java/com/nis/util/ServiceConfigTemplateUtil.java b/src/main/java/com/nis/util/ServiceConfigTemplateUtil.java index 1a10c3082..9bf2a1380 100644 --- a/src/main/java/com/nis/util/ServiceConfigTemplateUtil.java +++ b/src/main/java/com/nis/util/ServiceConfigTemplateUtil.java @@ -1,46 +1,66 @@ package com.nis.util; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; -import org.apache.commons.collections.map.CaseInsensitiveMap; import org.apache.log4j.Logger; -import org.dom4j.Attribute; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; +import com.beust.jcommander.internal.Sets; import com.nis.domain.FunctionServiceDict; +import jersey.repackaged.com.google.common.collect.Lists; + +@SuppressWarnings("all") public class ServiceConfigTemplateUtil { - private Logger logger = Logger.getLogger(getClass()); + private static final Logger logger = Logger.getLogger(ServiceConfigTemplateUtil.class); - private Node root; + private static Node root; + + static { + if(root == null) {//2018年12月28日11:37:50 fang 改为只加载一次,且方法改为 static + SAXReader reader = new SAXReader(); + org.dom4j.Document document = null; + String configPath = "/service/service_config.xml"; + InputStream is = null; + try { + is = ServiceConfigTemplateUtil.class.getResourceAsStream(configPath); + document = reader.read(is); + root = document.getRootElement(); + } catch (Exception e) { + logger.error(e.getMessage()); + e.printStackTrace(); + } finally { + if(is != null ){ + try { + is.close(); + } catch (IOException e) { } + } + } + } + } + /** * 配置文件内容 * @return */ public ServiceConfigTemplateUtil(){ - SAXReader reader = new SAXReader(); - org.dom4j.Document document = null; - String configPath = "/service/service_config.xml"; - try { - document = reader.read(ServiceConfigTemplateUtil.class.getResourceAsStream(configPath)); - root = document.getRootElement(); - } catch (Exception e) { - logger.error(e.getMessage()); - e.printStackTrace(); - } + } /** * 获取业务节点列表 * @return */ - public List getServiceNodeList(){ + public static List getServiceNodeList(){ List nodes = root.selectNodes("service"); return nodes; } @@ -48,7 +68,7 @@ public class ServiceConfigTemplateUtil { * 获取业务列表 * @return */ - public List> getServiceList(){ + public static List> getServiceList(){ List> list =new ArrayList(); List elements = root.selectNodes("service"); for(Element element:elements){ @@ -63,12 +83,47 @@ public class ServiceConfigTemplateUtil { } return list; } + + /** + * + * @return + */ + public static Set getCompileTableName(){ + Set result = Sets.newHashSet(); + List elements = root.selectNodes("service"); + for(Element element:elements){ + String ev = element.attribute("tableName").getStringValue(); + if(StringUtils.isNotBlank(ev)) { + result.add(ev.toLowerCase()); + } + } + return result; + } + + /** + * 根据类名 获取对应的 表名 + * @param className + * @return + */ + public static String getCfgTableNameByClassName(String className) { + if(className == null) return null; + List elements = root.selectNodes("service"); + for(Element element:elements){ + String ev = element.attribute("tableName").getStringValue(); + String cn = element.attribute("className").getStringValue(); + if(className.equalsIgnoreCase(cn)) { + return ev.toLowerCase(); + } + } + return null; + } + /** * * @param functionId * @return */ - public List> getServiceListByFunctionId(Integer functionId){ + public static List> getServiceListByFunctionId(Integer functionId){ List> list =new ArrayList(); if(!StringUtil.isEmpty(functionId)) { List serviceList = DictUtils.getFunctionServiceDictList(functionId); @@ -133,7 +188,7 @@ public class ServiceConfigTemplateUtil { * 获取业务配置列表 * @return */ - public List> getServiceCfgList(Element serviceNode){ + public static List> getServiceCfgList(Element serviceNode){ List> list = new ArrayList(); List elements = serviceNode.selectNodes("serviceCfg"); for(Element element:elements){ @@ -149,7 +204,7 @@ public class ServiceConfigTemplateUtil { * 获取用户自定义域列表 * @return */ - public List> getUserRegionList(Element serviceNode){ + public static List> getUserRegionList(Element serviceNode){ List> list = new ArrayList(); List elements = serviceNode.selectNodes("userRegion"); for(Element element:elements){ @@ -167,7 +222,7 @@ public class ServiceConfigTemplateUtil { * @param attribute * @return */ - public List getXmlParamListByTag(String tag,String attribute){ + public static List getXmlParamListByTag(String tag,String attribute){ List list =new ArrayList(); List elements = root.selectNodes(tag); for(Element element:elements){ @@ -196,6 +251,7 @@ public class ServiceConfigTemplateUtil { } + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/main/java/com/nis/web/dao/SchedulerDao.java b/src/main/java/com/nis/web/dao/SchedulerDao.java new file mode 100644 index 000000000..16110a94e --- /dev/null +++ b/src/main/java/com/nis/web/dao/SchedulerDao.java @@ -0,0 +1,76 @@ +package com.nis.web.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.nis.domain.ScheduleCfg; +import com.nis.domain.ScheduleExceInfo; +import com.nis.domain.configuration.BaseCfg; + +@MyBatisDao +public interface SchedulerDao extends CrudDao { + + + List findScheduleList(ScheduleCfg cfg); + + /** + * 查找最新的修改数据 + * @param id + * @param size + * @return + */ + List findNewlyCfg(@Param("id")Long id,@Param("limit")Long limit); + + /** + * 更新 del_flag 字段为删除标识 + * @param cfg + * @return + */ + int deleteByCompileId(ScheduleCfg cfg); + + /** + * 查找 配置 下发 最新记录 + * @param compileId + * @param isValid + * @return + */ + ScheduleExceInfo findScheduleExceNew(ScheduleExceInfo se); + + /** + * 修改配置表状态 + * @param tableName + * @param compileId + * @param isValid + * @return + */ + int updateCfgTableStatus(@Param("tableName")String tableName,@Param("compileId")Integer compileId,@Param("isValid")Integer isValid); + + /** + * 查询 配置信息 + * @param compileId + * @return + */ + BaseCfg getCfgTableInfo(@Param("tableName")String tableName,@Param("compileId")Integer compileId); + + /** + * 保存执行记录 + * @param exceInfo + * @return + */ + int insertScheduleExceLog(ScheduleExceInfo exceInfo); + + /** + * 保存最新记录表 + * @param exceInfo + * @return + */ + int insertScheduleExceNew(ScheduleExceInfo exceInfo); + /** + * 更新最新记录表 + * @param exceInfo + * @return + */ + int updateScheduleExceNew(ScheduleExceInfo exceInfo); + +} \ No newline at end of file diff --git a/src/main/java/com/nis/web/dao/SchedulerDao.xml b/src/main/java/com/nis/web/dao/SchedulerDao.xml new file mode 100644 index 000000000..26aaee47b --- /dev/null +++ b/src/main/java/com/nis/web/dao/SchedulerDao.xml @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + a.ID, + a.NAME, + a.cron_valid, + a.cron_invalid, + a.SERVICE_ID, + a.COMPILE_ID, + a.CFG_ID, + a.IS_VALID, + a.IS_AUDIT, + a.function_id, + a.CREATOR_ID, + a.CREATE_TIME, + a.EDITOR_ID, + a.EDIT_TIME, + a.table_name, + a.user_region1, + a.user_region2, + a.user_region3, + a.user_region4, + a.user_region5 + + + + + + + + + + + insert into schedule_cfg ( + NAME, + cron_valid, + cron_invalid, + SERVICE_ID, + COMPILE_ID, + CFG_ID, + IS_VALID, + IS_AUDIT, + function_id, + CREATOR_ID, + CREATE_TIME, + EDITOR_ID, + EDIT_TIME, + table_name, + user_region1, + user_region2, + user_region3, + user_region4, + user_region5 + ) values ( + #{name,jdbcType=VARCHAR}, + #{cronValid,jdbcType=VARCHAR}, + #{cronInvalid,jdbcType=VARCHAR}, + #{serviceId,jdbcType=INTEGER}, + #{compileId,jdbcType=INTEGER}, + #{cfgId,jdbcType=INTEGER}, + #{isValid,jdbcType=INTEGER}, + #{isAudit,jdbcType=INTEGER}, + #{functionId,jdbcType=INTEGER}, + #{creatorId,jdbcType=INTEGER}, + #{createTime,jdbcType=TIMESTAMP}, + #{editorId,jdbcType=INTEGER}, + #{editTime,jdbcType=TIMESTAMP}, + #{tableName,jdbcType=VARCHAR}, + #{userRegion1,jdbcType=VARCHAR}, + #{userRegion2,jdbcType=VARCHAR}, + #{userRegion3,jdbcType=VARCHAR}, + #{userRegion4,jdbcType=VARCHAR}, + #{userRegion5,jdbcType=VARCHAR} + ) + + + + + update schedule_cfg + + + editor_Id = #{editorId,jdbcType=VARCHAR}, + + + edit_Time = #{editTime,jdbcType=TIMESTAMP}, + + del_flag = #{DEL_FLAG_DELETE} + + WHERE compile_Id = #{compileId} and del_flag =1 + + + + + + + + + + update ${tableName} set is_valid = #{isValid} ,is_audit = 1 where compile_id = #{compileId} + + + + + + + + INSERT INTO schedule_exce_log ( + schedule_id, + exce_time, + issue_status, + issue_result, + error_info, + compile_id, + is_issue + ) VALUES ( + #{scheduleId}, + #{exceTime}, + #{issueStatus}, + #{issueResult}, + #{errorInfo}, + #{compileId}, + 0 + ); + + + + + INSERT INTO schedule_exce_new ( + schedule_id, + exce_time, + issue_status, + issue_result, + error_info, + compile_id, + is_issue + ) VALUES ( + #{scheduleId}, + #{exceTime}, + #{issueStatus}, + #{issueResult}, + #{errorInfo}, + #{compileId}, + 0 + ); + + + + + UPDATE schedule_exce_new + + + schedule_id = #{scheduleId}, + + + exce_time = #{exceTime}, + + + issue_result = #{issueResult}, + + + error_info = #{errorInfo}, + + + is_issue = #{isIssue}, + + + WHERE + compile_Id = #{compileId} and issue_status = #{issueStatus} + + + + + \ No newline at end of file diff --git a/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.java b/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.java index 887173001..2e17cf7e9 100644 --- a/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.java +++ b/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.java @@ -99,4 +99,6 @@ public interface ConfigSynchronizationDao { public List getAppIpFeatureList(BaseCfg entity); public void updateCfgStatus(BaseCfg entity); + + public PxyObjSpoofingIpPool getPxyObjSpoofingIpPool(Long cfgId); } diff --git a/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.xml b/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.xml index 9b76df62b..7c8cc7dac 100644 --- a/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.xml +++ b/src/main/java/com/nis/web/dao/configuration/ConfigSynchronizationDao.xml @@ -733,6 +733,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + a.cfg_id,a.cfg_desc,a.action,a.is_valid,a.is_audit,a.creator_id,a.audit_time, a.service_id,a.request_id,a.compile_id,a.is_area_effective,a.classify,a.attribute,a.lable, @@ -877,12 +910,13 @@ a.ip_type,a.src_ip_address,a.ip_pattern,a.port_pattern,a.src_port ,a.protocol,a.direction,a.dest_port,a.dest_ip_address,a.cfg_type,a.compile_id - - a.CFG_ID, a.CFG_DESC,a.CFG_REGION_CODE, a.IP_TYPE, a.IP_ADDRESS, - a.DIRECTION,a.PROTOCOL,a.IS_VALID,a.IS_AUDIT,a.location,a.port, - a.CREATOR_ID,a.CREATE_TIME,a.EDITOR_ID,a.EDIT_TIME,a.AUDITOR_ID,a.AUDIT_TIME, - a.SERVICE_ID,a.REQUEST_ID,a.COMPILE_ID,a.IS_AREA_EFFECTIVE,a.CLASSIFY, - a.ATTRIBUTE,a.LABLE,a.AREA_EFFECTIVE_IDS,a.FUNCTION_ID,a.GROUP_ID,a.user_region + + + r.CFG_ID, r.CFG_DESC,r.CFG_REGION_CODE, r.IP_TYPE, r.IP_ADDRESS, + r.DIRECTION,r.PROTOCOL,r.IS_VALID,r.IS_AUDIT,r.location,r.port, + r.CREATOR_ID,r.CREATE_TIME,r.EDITOR_ID,r.EDIT_TIME,r.AUDITOR_ID,r.AUDIT_TIME, + r.SERVICE_ID,r.REQUEST_ID,r.COMPILE_ID,r.IS_AREA_EFFECTIVE,r.CLASSIFY, + r.ATTRIBUTE,r.LABLE,r.AREA_EFFECTIVE_IDS,r.FUNCTION_ID,r.GROUP_ID,r.user_region + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mybatis-config.xml b/src/main/resources/mybatis-config.xml index b8aadf01f..2e303ffd3 100644 --- a/src/main/resources/mybatis-config.xml +++ b/src/main/resources/mybatis-config.xml @@ -1,70 +1,74 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/quartz.properties b/src/main/resources/quartz.properties new file mode 100644 index 000000000..dbbc381a5 --- /dev/null +++ b/src/main/resources/quartz.properties @@ -0,0 +1,17 @@ +#################### quartz 相关配置文件 ######################### + +#Main Scheduler Settings +org.quartz.scheduler.instanceName=NTCScheduler +org.quartz.scheduler.instanceId=AUTO +org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer=true +org.quartz.scheduler.skipUpdateCheck=true +org.quartz.scheduler.batchTriggerAcquisitionMaxCount=100 +org.quartz.threadPool.threadCount=10 + +#Configure JDBC-JobStoreTX +org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX +org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate +org.quartz.jobStore.tablePrefix=QRTZ_ +org.quartz.jobStore.isClustered=true +org.quartz.jobStore.acquireTriggersWithinLock=true +org.quartz.jobStore.clusterCheckinInterval = 30000 \ No newline at end of file diff --git a/src/main/resources/service/service_config.xml b/src/main/resources/service/service_config.xml index 98273fb75..c573831b3 100644 --- a/src/main/resources/service/service_config.xml +++ b/src/main/resources/service/service_config.xml @@ -11,13 +11,13 @@ - - + + + + + + - @@ -32,13 +32,13 @@ - + - - - + --> + + @@ -279,21 +279,22 @@ - + - + + - + @@ -301,21 +302,21 @@ - + - + - + @@ -323,7 +324,7 @@ - + diff --git a/src/main/resources/shiro.ini b/src/main/resources/shiro.ini new file mode 100644 index 000000000..4b19e1096 --- /dev/null +++ b/src/main/resources/shiro.ini @@ -0,0 +1,2 @@ +[users] +admin=admin!@#,Superman \ No newline at end of file diff --git a/src/main/resources/sql/20190102/quartz_mysql_innodb.sql b/src/main/resources/sql/20190102/quartz_mysql_innodb.sql new file mode 100644 index 000000000..467a1d588 --- /dev/null +++ b/src/main/resources/sql/20190102/quartz_mysql_innodb.sql @@ -0,0 +1,179 @@ +# +# In your Quartz properties file, you'll need to set +# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate +# +# +# By: Ron Cordell - roncordell +# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM. + +DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; +DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; +DROP TABLE IF EXISTS QRTZ_LOCKS; +DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; +DROP TABLE IF EXISTS QRTZ_CALENDARS; + +CREATE TABLE QRTZ_JOB_DETAILS( +SCHED_NAME VARCHAR(120) NOT NULL, +JOB_NAME VARCHAR(200) NOT NULL, +JOB_GROUP VARCHAR(200) NOT NULL, +DESCRIPTION VARCHAR(250) NULL, +JOB_CLASS_NAME VARCHAR(250) NOT NULL, +IS_DURABLE VARCHAR(1) NOT NULL, +IS_NONCONCURRENT VARCHAR(1) NOT NULL, +IS_UPDATE_DATA VARCHAR(1) NOT NULL, +REQUESTS_RECOVERY VARCHAR(1) NOT NULL, +JOB_DATA BLOB NULL, +PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_TRIGGERS ( +SCHED_NAME VARCHAR(120) NOT NULL, +TRIGGER_NAME VARCHAR(200) NOT NULL, +TRIGGER_GROUP VARCHAR(200) NOT NULL, +JOB_NAME VARCHAR(200) NOT NULL, +JOB_GROUP VARCHAR(200) NOT NULL, +DESCRIPTION VARCHAR(250) NULL, +NEXT_FIRE_TIME BIGINT(13) NULL, +PREV_FIRE_TIME BIGINT(13) NULL, +PRIORITY INTEGER NULL, +TRIGGER_STATE VARCHAR(16) NOT NULL, +TRIGGER_TYPE VARCHAR(8) NOT NULL, +START_TIME BIGINT(13) NOT NULL, +END_TIME BIGINT(13) NULL, +CALENDAR_NAME VARCHAR(200) NULL, +MISFIRE_INSTR SMALLINT(2) NULL, +JOB_DATA BLOB NULL, +PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), +FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) +REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_SIMPLE_TRIGGERS ( +SCHED_NAME VARCHAR(120) NOT NULL, +TRIGGER_NAME VARCHAR(200) NOT NULL, +TRIGGER_GROUP VARCHAR(200) NOT NULL, +REPEAT_COUNT BIGINT(7) NOT NULL, +REPEAT_INTERVAL BIGINT(12) NOT NULL, +TIMES_TRIGGERED BIGINT(10) NOT NULL, +PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), +FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_CRON_TRIGGERS ( +SCHED_NAME VARCHAR(120) NOT NULL, +TRIGGER_NAME VARCHAR(200) NOT NULL, +TRIGGER_GROUP VARCHAR(200) NOT NULL, +CRON_EXPRESSION VARCHAR(120) NOT NULL, +TIME_ZONE_ID VARCHAR(80), +PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), +FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_SIMPROP_TRIGGERS + ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + STR_PROP_1 VARCHAR(512) NULL, + STR_PROP_2 VARCHAR(512) NULL, + STR_PROP_3 VARCHAR(512) NULL, + INT_PROP_1 INT NULL, + INT_PROP_2 INT NULL, + LONG_PROP_1 BIGINT NULL, + LONG_PROP_2 BIGINT NULL, + DEC_PROP_1 NUMERIC(13,4) NULL, + DEC_PROP_2 NUMERIC(13,4) NULL, + BOOL_PROP_1 VARCHAR(1) NULL, + BOOL_PROP_2 VARCHAR(1) NULL, + PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_BLOB_TRIGGERS ( +SCHED_NAME VARCHAR(120) NOT NULL, +TRIGGER_NAME VARCHAR(200) NOT NULL, +TRIGGER_GROUP VARCHAR(200) NOT NULL, +BLOB_DATA BLOB NULL, +PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), +INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP), +FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) +REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_CALENDARS ( +SCHED_NAME VARCHAR(120) NOT NULL, +CALENDAR_NAME VARCHAR(200) NOT NULL, +CALENDAR BLOB NOT NULL, +PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS ( +SCHED_NAME VARCHAR(120) NOT NULL, +TRIGGER_GROUP VARCHAR(200) NOT NULL, +PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_FIRED_TRIGGERS ( +SCHED_NAME VARCHAR(120) NOT NULL, +ENTRY_ID VARCHAR(95) NOT NULL, +TRIGGER_NAME VARCHAR(200) NOT NULL, +TRIGGER_GROUP VARCHAR(200) NOT NULL, +INSTANCE_NAME VARCHAR(200) NOT NULL, +FIRED_TIME BIGINT(13) NOT NULL, +SCHED_TIME BIGINT(13) NOT NULL, +PRIORITY INTEGER NOT NULL, +STATE VARCHAR(16) NOT NULL, +JOB_NAME VARCHAR(200) NULL, +JOB_GROUP VARCHAR(200) NULL, +IS_NONCONCURRENT VARCHAR(1) NULL, +REQUESTS_RECOVERY VARCHAR(1) NULL, +PRIMARY KEY (SCHED_NAME,ENTRY_ID)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_SCHEDULER_STATE ( +SCHED_NAME VARCHAR(120) NOT NULL, +INSTANCE_NAME VARCHAR(200) NOT NULL, +LAST_CHECKIN_TIME BIGINT(13) NOT NULL, +CHECKIN_INTERVAL BIGINT(13) NOT NULL, +PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)) +ENGINE=InnoDB; + +CREATE TABLE QRTZ_LOCKS ( +SCHED_NAME VARCHAR(120) NOT NULL, +LOCK_NAME VARCHAR(40) NOT NULL, +PRIMARY KEY (SCHED_NAME,LOCK_NAME)) +ENGINE=InnoDB; + +CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY); +CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP); + +CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME); +CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); +CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); + +CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME); +CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); +CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP); +CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); +CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); + +commit; diff --git a/src/main/resources/sql/20190102/schedule.sql b/src/main/resources/sql/20190102/schedule.sql new file mode 100644 index 000000000..0ff06f870 --- /dev/null +++ b/src/main/resources/sql/20190102/schedule.sql @@ -0,0 +1,81 @@ +/* + Navicat Premium Data Transfer + + Source Server : 本机 + Source Server Type : MariaDB + Source Server Version : 100214 + Source Host : 127.0.0.1:3306 + Source Schema : ntc + + Target Server Type : MariaDB + Target Server Version : 100214 + File Encoding : 65001 + + Date: 02/01/2019 17:15:01 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for schedule_cfg +-- ---------------------------- +DROP TABLE IF EXISTS `schedule_cfg`; +CREATE TABLE `schedule_cfg` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增', + `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时任务名称,预留', + `cron_valid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时:月份', + `cron_invalid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时:天', + `cfg_id` bigint(20) NOT NULL COMMENT '配置表id', + `compile_id` bigint(20) NOT NULL COMMENT '编译id', + `service_id` int(11) NOT NULL COMMENT '业务id', + `is_valid` int(11) NOT NULL DEFAULT 1 COMMENT '配置生效标识,1:有效,0:无效', + `is_audit` int(1) NULL DEFAULT NULL COMMENT '审核状态', + `function_id` int(11) NULL DEFAULT NULL COMMENT 'function id', + `creator_id` int(11) NULL DEFAULT NULL COMMENT '创建人id', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `editor_id` int(11) NULL DEFAULT NULL COMMENT '修改人id', + `edit_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `table_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表名', + `user_region1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `user_region2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `user_region3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `user_region4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `user_region5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `del_flag` int(1) NULL DEFAULT 1 COMMENT '删除标识,定时任务是否有效,默认:1', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for schedule_exce_log +-- ---------------------------- +DROP TABLE IF EXISTS `schedule_exce_log`; +CREATE TABLE `schedule_exce_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增', + `schedule_id` bigint(20) NOT NULL COMMENT 'schedule_info 表的主键', + `exce_time` datetime(0) NULL DEFAULT NULL COMMENT '最新执行时间', + `issue_status` int(255) NULL DEFAULT NULL COMMENT '下发状态:1:生效,0:失效', + `issue_result` int(255) NULL DEFAULT NULL COMMENT '下发结果:1:成功,0:失败', + `error_info` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '下发失败原因', + `compile_id` bigint(20) NULL DEFAULT NULL COMMENT '编译id', + `is_issue` int(1) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for schedule_exce_new +-- ---------------------------- +DROP TABLE IF EXISTS `schedule_exce_new`; +CREATE TABLE `schedule_exce_new` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增', + `schedule_id` bigint(20) NOT NULL COMMENT 'schedule_info 表的主键', + `exce_time` datetime(0) NULL DEFAULT NULL COMMENT '最新执行时间', + `issue_status` int(255) NULL DEFAULT NULL COMMENT '下发状态:1:生效,0:失效', + `issue_result` int(255) NULL DEFAULT NULL COMMENT '下发结果:1:成功,0:失败', + `error_info` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '下发失败原因', + `compile_id` bigint(20) NULL DEFAULT NULL COMMENT '编译id', + `is_issue` int(255) NULL DEFAULT 0 COMMENT '是否需要下发配置,1:是,0:否', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/webapp/WEB-INF/tags/sys/delRow.tag b/src/main/webapp/WEB-INF/tags/sys/delRow.tag index 690e37e40..b495b5d80 100644 --- a/src/main/webapp/WEB-INF/tags/sys/delRow.tag +++ b/src/main/webapp/WEB-INF/tags/sys/delRow.tag @@ -109,6 +109,12 @@ function del(url){ function update(url){ var checkboxes=$("#${id} ${value} tbody tr td input.i-checks:checkbox"); var cked = $("tbody tr td input.i-checks:checkbox:checked"); + + var schedulerFlag = $(cked).parent().parent().find(".schedulerFlag").find("span").attr("isScheduler"); + if(schedulerFlag!= "undefined" && schedulerFlag=="yes"){//验证配置是否是定时任务,如果是定时任务,不允许修改 + top.$.jBox.tip("", ""); + return; + } if($(checkboxes).filter(":checked").length==1){ if(cked.val()==1){ top.$.jBox.tip("", ""); @@ -137,6 +143,10 @@ function passOpt(url){ var checkboxes=$("#${id} ${value} tbody tr td input.i-checks:checkbox"); if($(checkboxes).filter(":checked").length>0){ + if(validateIsScheduler(checkboxes)){//验证配置是否是定时任务,如果是定时任务,不允许手动审核 + top.$.jBox.tip("", ""); + return; + } if(validateAllNoAudit(checkboxes)){ top.$.jBox.tip("", ""); return; @@ -435,6 +445,17 @@ function cancelPassOpt(url){ }); return flag; } + function validateIsScheduler(checkboxes){ + var flag = false; + $(checkboxes).filter(":checked").each(function(){ + var schedulerFlag = $(this).parent().parent().find(".schedulerFlag").find("span").attr("isScheduler"); + if(schedulerFlag!= "undefined" && schedulerFlag=="yes"){ + flag = true; + return; + } + }); + return flag; + } //导出 function exportData(url,maxRow,searchUrl,exType){ var column=[]; diff --git a/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipForm.jsp b/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipForm.jsp index 821dbe16d..1ee5a1d2d 100644 --- a/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipForm.jsp +++ b/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipForm.jsp @@ -737,6 +737,8 @@ var showHideIPSECProtocol=function(obj){ <%@include file="/WEB-INF/include/form/areaInfo.jsp"%>
<%@include file="/WEB-INF/include/form/basicInfo.jsp"%> +
+ <%@include file="/WEB-INF/include/form/scheduleNew.jsp"%>
diff --git a/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipSubList.jsp b/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipSubList.jsp index 846b0dfa8..afb4a7852 100644 --- a/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipSubList.jsp +++ b/src/main/webapp/WEB-INF/views/cfg/ipaddr/ipSubList.jsp @@ -19,6 +19,15 @@
+ +
+ + +
+
+ +
@@ -245,4 +254,10 @@ + + +
+ <%@include file="/WEB-INF/include/form/scheduleNewSubList.jsp"%> +
+
\ No newline at end of file diff --git a/src/main/webapp/static/global/plugins/jquery-cron/AUTHORS b/src/main/webapp/static/global/plugins/jquery-cron/AUTHORS new file mode 100644 index 000000000..aec16d1ca --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-cron/AUTHORS @@ -0,0 +1 @@ +Shawn Chin diff --git a/src/main/webapp/static/global/plugins/jquery-cron/LICENSE b/src/main/webapp/static/global/plugins/jquery-cron/LICENSE new file mode 100644 index 000000000..05342c282 --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-cron/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010 Shawn Chin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/main/webapp/static/global/plugins/jquery-cron/README.md b/src/main/webapp/static/global/plugins/jquery-cron/README.md new file mode 100644 index 000000000..51057a288 --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-cron/README.md @@ -0,0 +1,40 @@ +# jQuery plugin: cron + +jquery-cron is a [jQuery] plugin for +presenting a simplified interface for users to specify cron entries. + +Check out the [jquery-cron] website for more information. + +There is much to be done on the flexibility and robustness front, +and we welcome contributions and bug fixes. Feel free to fork +and send us pull requests! + +## Dependencies + + * [jQuery] + * [jquery-gentleSelect] (optional) + +## Usage + +To use this plugin, one simply needs to load [jQuery] +and the JS/CSS scripts for jquery-cron, then attach it an empty `
` +on DOM ready: + + $(document).ready(function() { + $('#selector').cron(); + }); + + +For more options, see the [jquery-cron] website. + + +## Others + +Copyright (c) 2010-2013, Shawn Chin. + +This project is licensed under the [MIT license]. + + [jQuery]: http://jquery.com "jQuery" + [jquery-cron]: http://shawnchin.github.com/jquery-cron "jquery-cron" + [jquery-gentleSelect]: http://shawnchin.github.com/jquery-gentleSelect "jquery-gentleSelect" + [MIT License]: http://www.opensource.org/licenses/mit-license.php "MIT License" diff --git a/src/main/webapp/static/global/plugins/jquery-cron/cron/img/disk.png b/src/main/webapp/static/global/plugins/jquery-cron/cron/img/disk.png new file mode 100644 index 000000000..99d532e8b Binary files /dev/null and b/src/main/webapp/static/global/plugins/jquery-cron/cron/img/disk.png differ diff --git a/src/main/webapp/static/global/plugins/jquery-cron/cron/img/loading.gif b/src/main/webapp/static/global/plugins/jquery-cron/cron/img/loading.gif new file mode 100644 index 000000000..d0bce1542 Binary files /dev/null and b/src/main/webapp/static/global/plugins/jquery-cron/cron/img/loading.gif differ diff --git a/src/main/webapp/static/global/plugins/jquery-cron/cron/jquery-cron-min.js b/src/main/webapp/static/global/plugins/jquery-cron/cron/jquery-cron-min.js new file mode 100644 index 000000000..1b678cc6c --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-cron/cron/jquery-cron-min.js @@ -0,0 +1 @@ +(function(e){var n={initial:"* * * * *",minuteOpts:{minWidth:100,itemWidth:30,columns:4,rows:undefined,title:"Minutes Past the Hour"},timeHourOpts:{minWidth:100,itemWidth:20,columns:2,rows:undefined,title:"Time: Hour"},domOpts:{minWidth:100,itemWidth:30,columns:undefined,rows:10,title:"Day of Month"},monthOpts:{minWidth:100,itemWidth:100,columns:2,rows:undefined,title:undefined},dowOpts:{minWidth:100,itemWidth:undefined,columns:undefined,rows:undefined,title:undefined},timeMinuteOpts:{minWidth:100,itemWidth:20,columns:4,rows:undefined,title:"Time: Minute"},effectOpts:{openSpeed:400,closeSpeed:400,openEffect:"slide",closeEffect:"slide",hideOnMouseOut:true},url_set:undefined,customValues:undefined,onChange:undefined,useGentleSelect:false};var y="";for(var u=0;u<60;u++){var t=(u<10)?"0":"";y+="\n"}var d="";for(var u=0;u<24;u++){var t=(u<10)?"0":"";d+="\n"}var v="";for(var u=1;u<32;u++){if(u==1||u==21||u==31){var c="st"}else{if(u==2||u==22){var c="nd"}else{if(u==3||u==23){var c="rd"}else{var c="th"}}}v+="\n"}var h="";var l=["January","February","March","April","May","June","July","August","September","October","November","December"];for(var u=0;u"+l[u]+"\n"}var s="";var g=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];for(var u=0;u"+g[u]+"\n"}var r="";var b=["day","week","month","year"];for(var u=0;u"+b[u]+"\n"}var p={minute:[],hour:["mins"],day:["time"],week:["dow","time"],month:["dom","time"],year:["dom","month","time"]};var w={minute:/^(\*\s){4}\*$/,hour:/^\d{1,2}\s(\*\s){3}\*$/,day:/^(\d{1,2}\s){2}(\*\s){2}\*$/,week:/^(\d{1,2}\s){2}(\*\s){2}\d{1,2}$/,month:/^(\d{1,2}\s){3}\*\s\*$/,year:/^(\d{1,2}\s){4}\*$/};function a(i){if(typeof i=="undefined"){return false}else{return true}}function q(i){return(!a(i)||typeof i=="object")}function z(A,j){if(a(j.customValues)){for(key in j.customValues){if(A==j.customValues[key]){return key}}}var E=/^((\d{1,2}|\*)\s){4}(\d{1,2}|\*)$/;if(typeof A!="string"||!E.test(A)){e.error("cron: invalid initial value");return undefined}var C=A.split(" ");var D=[0,0,1,1,0];var G=[59,23,31,12,6];for(var B=0;B=D[B]){continue}e.error("cron: invalid value found (col "+(B+1)+") in "+o.initial);return undefined}for(var H in w){if(w[H].test(A)){return H}}e.error("cron: valid but unsupported cron format. sorry.");return undefined}function f(j,i){if(!a(z(i.initial,i))){return true}if(!q(i.customValues)){return true}if(a(i.customValues)){for(key in i.customValues){if(w.hasOwnProperty(key)){e.error("cron: reserved keyword '"+key+"' should not be used as customValues key.");return true}}}return false}function k(B){var i=B.data("block");var j=hour=day=month=dow="*";var A=i.period.find("select").val();switch(A){case"minute":break;case"hour":j=i.mins.find("select").val();break;case"day":j=i.time.find("select.cron-time-min").val();hour=i.time.find("select.cron-time-hour").val();break;case"week":j=i.time.find("select.cron-time-min").val();hour=i.time.find("select.cron-time-hour").val();dow=i.dow.find("select").val();break;case"month":j=i.time.find("select.cron-time-min").val();hour=i.time.find("select.cron-time-hour").val();day=i.dom.find("select").val();break;case"year":j=i.time.find("select.cron-time-min").val();hour=i.time.find("select.cron-time-hour").val();day=i.dom.find("select").val();month=i.month.find("select").val();break;default:return A}return[j,hour,day,month,dow].join(" ")}var x={init:function(i){var G=i?i:{};var B=e.extend([],n,G);var j=e.extend({},n.effectOpts,G.effectOpts);e.extend(B,{minuteOpts:e.extend({},n.minuteOpts,j,G.minuteOpts),domOpts:e.extend({},n.domOpts,j,G.domOpts),monthOpts:e.extend({},n.monthOpts,j,G.monthOpts),dowOpts:e.extend({},n.dowOpts,j,G.dowOpts),timeHourOpts:e.extend({},n.timeHourOpts,j,G.timeHourOpts),timeMinuteOpts:e.extend({},n.timeMinuteOpts,j,G.timeMinuteOpts)});if(f(this,B)){return this}var C=[],A="",D=B.customValues;if(a(D)){for(var F in D){A+="\n"}}C.period=e("Every ").appendTo(this).data("root",this);var E=C.period.find("select");E.bind("change.cron",m.periodChanged).data("root",this);if(B.useGentleSelect){E.gentleSelect(j)}C.dom=e(" on the ").appendTo(this).data("root",this);E=C.dom.find("select").data("root",this);if(B.useGentleSelect){E.gentleSelect(B.domOpts)}C.month=e(" of ").appendTo(this).data("root",this);E=C.month.find("select").data("root",this);if(B.useGentleSelect){E.gentleSelect(B.monthOpts)}C.mins=e(" at minutes past the hour ").appendTo(this).data("root",this);E=C.mins.find("select").data("root",this);if(B.useGentleSelect){E.gentleSelect(B.minuteOpts)}C.dow=e(" on ").appendTo(this).data("root",this);E=C.dow.find("select").data("root",this);if(B.useGentleSelect){E.gentleSelect(B.dowOpts)}C.time=e(" at :" + custom_periods + + str_opt_period + " ") + .appendTo(this) + .data("root", this); + + var select = block["period"].find("select"); + select.bind("change.cron", event_handlers.periodChanged) + .data("root", this); + if (o.useGentleSelect) select.gentleSelect(eo); + + block["dom"] = $("" + + " on the ") + .appendTo(this) + .data("root", this); + + select = block["dom"].find("select").data("root", this); + if (o.useGentleSelect) select.gentleSelect(o.domOpts); + + block["month"] = $("" + + " of ") + .appendTo(this) + .data("root", this); + + select = block["month"].find("select").data("root", this); + if (o.useGentleSelect) select.gentleSelect(o.monthOpts); + + block["mins"] = $("" + + " at minutes past the hour ") + .appendTo(this) + .data("root", this); + + select = block["mins"].find("select").data("root", this); + if (o.useGentleSelect) select.gentleSelect(o.minuteOpts); + + block["dow"] = $("" + + " on ") + .appendTo(this) + .data("root", this); + + select = block["dow"].find("select").data("root", this); + if (o.useGentleSelect) select.gentleSelect(o.dowOpts); + + block["time"] = $("" + + " at : .... + * + */ +(function($) { + + var defaults = { + minWidth : 100, // only applies if columns and itemWidth not set + itemWidth : undefined, + columns : undefined, + rows : undefined, + title : undefined, + prompt : "Make A Selection", + maxDisplay: 0, // set to 0 for unlimited + openSpeed : 400, + closeSpeed : 400, + openEffect : "slide", + closeEffect : "slide", + hideOnMouseOut : true + } + + function defined(obj) { + if (typeof obj == "undefined") { return false; } + else { return true; } + } + + function hasError(c, o) { + if (defined(o.columns) && defined(o.rows)) { + $.error("gentleSelect: You cannot supply both 'rows' and 'columns'"); + return true; + } + if (defined(o.columns) && !defined(o.itemWidth)) { + $.error("gentleSelect: itemWidth must be supplied if 'columns' is specified"); + return true; + } + if (defined(o.rows) && !defined(o.itemWidth)) { + $.error("gentleSelect: itemWidth must be supplied if 'rows' is specified"); + return true; + } + if (!defined(o.openSpeed) || typeof o.openSpeed != "number" && + (typeof o.openSpeed == "string" && (o.openSpeed != "slow" && o.openSpeed != "fast"))) { + $.error("gentleSelect: openSpeed must be an integer or \"slow\" or \"fast\""); + return true; + } + if (!defined(o.closeSpeed) || typeof o.closeSpeed != "number" && + (typeof o.closeSpeed == "string" && (o.closeSpeed != "slow" && o.closeSpeed != "fast"))) { + $.error("gentleSelect: closeSpeed must be an integer or \"slow\" or \"fast\""); + return true; + } + if (!defined(o.openEffect) || (o.openEffect != "fade" && o.openEffect != "slide")) { + $.error("gentleSelect: openEffect must be either 'fade' or 'slide'!"); + return true; + } + if (!defined(o.closeEffect)|| (o.closeEffect != "fade" && o.closeEffect != "slide")) { + $.error("gentleSelect: closeEffect must be either 'fade' or 'slide'!"); + return true; + } + if (!defined(o.hideOnMouseOut) || (typeof o.hideOnMouseOut != "boolean")) { + $.error("gentleSelect: hideOnMouseOut must be supplied and either \"true\" or \"false\"!"); + return true; + } + return false; + } + + function optionOverrides(c, o) { + if (c.attr("multiple")) { + o.hideOnMouseOut = true; // must be true or dialog will never hide + } + } + + function getSelectedAsText(elemList, opts) { + // If no items selected, return prompt + if (elemList.length < 1) { return opts.prompt; } + + // Truncate if exceed maxDisplay + if (opts.maxDisplay != 0 && elemList.length > opts.maxDisplay) { + var arr = elemList.slice(0, opts.maxDisplay).map(function(){return $(this).text();}); + arr.push("..."); + } else { + var arr = elemList.map(function(){return $(this).text();}); + } + return arr.get().join(", "); + } + + var methods = { + init : function(options) { + var o = $.extend({}, defaults, options); + + if (hasError(this, o)) { return this; }; // check for errors + optionOverrides(this, o); // + this.hide(); // hide original select box + + // initialise to replace select box + label_text = getSelectedAsText(this.find(":selected"), o); + var label = $("" + label_text + "") + .insertBefore(this) + .bind("mouseenter.gentleselect", event_handlers.labelHoverIn) + .bind("mouseleave.gentleselect", event_handlers.labelHoverOut) + .bind("click.gentleselect", event_handlers.labelClick) + .data("root", this); + this.data("label", label) + .data("options", o); + + // generate list of options + var ul = $("
    "); + this.find("option").each(function() { + var li = $("
  • " + $(this).text() + "
  • ") + .data("value", $(this).attr("value")) + .data("name", $(this).text()) + .appendTo(ul); + if ($(this).attr("selected")) { li.addClass("selected"); } + }); + + // build dialog box + var dialog = $("
    ") + .append(ul) + .insertAfter(label) + .bind("click.gentleselect", event_handlers.dialogClick) + .bind("mouseleave.gentleselect", event_handlers.dialogHoverOut) + .data("label", label) + .data("root", this); + this.data("dialog", dialog); + + // if to be displayed in columns + if (defined(o.columns) || defined(o.rows)) { + + // Update CSS + ul.css("float", "left") + .find("li").width(o.itemWidth).css("float","left"); + + var f = ul.find("li:first"); + var actualWidth = o.itemWidth + + parseInt(f.css("padding-left")) + + parseInt(f.css("padding-right")); + var elemCount = ul.find("li").length; + if (defined(o.columns)) { + var cols = parseInt(o.columns); + var rows = Math.ceil(elemCount / cols); + } else { + var rows = parseInt(o.rows); + var cols = Math.ceil(elemCount / rows); + } + dialog.width(actualWidth * cols); + + // add padding + for (var i = 0; i < (rows * cols) - elemCount; i++) { + $("
  •  
  • ").appendTo(ul); + } + + // reorder elements + var ptr = []; + var idx = 0; + ul.find("li").each(function() { + if (idx < rows) { + ptr[idx] = $(this); + } else { + var p = idx % rows; + $(this).insertAfter(ptr[p]); + ptr[p] = $(this); + } + idx++; + }); + } else if (typeof o.minWidth == "number") { + dialog.css("min-width", o.minWidth); + } + + if (defined(o.title)) { + $("
    " + o.title + "
    ").prependTo(dialog); + } + + // ESC key should hide all dialog boxes + $(document).bind("keyup.gentleselect", event_handlers.keyUp); + + return this; + }, + + // if select box was updated externally, we need to bring everything + // else up to speed. + update : function() { + var opts = this.data("options"); + + // Update li with selected data + var v = (this.attr("multiple")) ? this.val() : [this.val()]; + $("li", this.data("dialog")).each(function() { + var $li = $(this); + var isSelected = ($.inArray($li.data("value"), v) != -1); + $li.toggleClass("selected", isSelected); + }); + + // Update label + var label = getSelectedAsText(this.find(":selected"), opts); + this.data("label").text(label); + + return this; + } + }; + + var event_handlers = { + + labelHoverIn : function() { + $(this).addClass('gentleselect-label-highlight'); + }, + + labelHoverOut : function() { + $(this).removeClass('gentleselect-label-highlight'); + }, + + labelClick : function() { + var $this = $(this); + var pos = $this.position(); + var root = $this.data("root"); + var opts = root.data("options"); + var dialog = root.data("dialog") + .css("top", pos.top + $this.height()) + .css("left", pos.left + 1); + if (opts.openEffect == "fade") { + dialog.fadeIn(opts.openSpeed); + } else { + dialog.slideDown(opts.openSpeed); + } + }, + + dialogHoverOut : function() { + var $this = $(this); + if ($this.data("root").data("options").hideOnMouseOut) { + $this.hide(); + } + }, + + dialogClick : function(e) { + var clicked = $(e.target); + var $this = $(this); + var root = $this.data("root"); + var opts = root.data("options"); + if (!root.attr("multiple")) { + if (opts.closeEffect == "fade") { + $this.fadeOut(opts.closeSpeed); + } else { + $this.slideUp(opts.closeSpeed); + } + } + + if (clicked.is("li") && !clicked.hasClass("gentleselect-dummy")) { + var value = clicked.data("value"); + var name = clicked.data("name"); + var label = $this.data("label") + + if ($this.data("root").attr("multiple")) { + clicked.toggleClass("selected"); + var s = $this.find("li.selected"); + label.text(getSelectedAsText(s, opts)); + var v = s.map(function(){ return $(this).data("value"); }); + // update actual selectbox and trigger change event + root.val(v.get()).trigger("change"); + } else { + $this.find("li.selected").removeClass("selected"); + clicked.addClass("selected"); + label.text(clicked.data("name")); + // update actual selectbox and trigger change event + root.val(value).trigger("change"); + } + } + }, + + keyUp : function(e) { + if (e.keyCode == 27 ) { // ESC + $(".gentleselect-dialog").hide(); + } + } + }; + + $.fn.gentleSelect = function(method) { + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || ! method) { + return methods.init.apply(this, arguments); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.gentleSelect' ); + } + }; + + +})(jQuery); diff --git a/src/main/webapp/static/global/plugins/jquery-cron/index.html b/src/main/webapp/static/global/plugins/jquery-cron/index.html new file mode 100644 index 000000000..ebd146c53 --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-cron/index.html @@ -0,0 +1,384 @@ + + + + + jquery-cron : a jQuery plugin + + + + + + + + + + +
    +

    jQuery plugin: cron

    + +

    Introduction

    +

    + jquery-cron is a jQuery plugin for + presenting a simplified interface for users to specify cron entries. +

    + +

    + Instead of having to specify the five elements of a cron entry (minute, + hour, day of month, month, day of week), jquery-cron provides a simpler + interface for users to enter the more common combinations. For example: +

    + +
    +
    +

    Generated cron entry:

    +
    + + Or, with useGentleSelect enabled: + +
    +
    +

    Generated cron entry:

    +
    + +

    + In addition, the customValues + option can be used to provide a list of canned cron entries. This allow users to + cater for common use cases as well as enable more complex cron entries. +

    + +

    + There is much room for improvements and we welcome contributions + and bug fixes. Feel free to fork the project + and send us pull requests! +

    + +

    Download

    + + +

    TODO

    +
      +
    • Support multiple entries per field
    • +
    • implement option to add CSS class (simplify customisation)
    • +
    • make the AJAX POST functionality more generic
    • +
    +

    Usage

    + +

    + To use this plugin, one simply needs to load jQuery + and the JS/CSS scripts for jquery-cron: +

    + +
    +<script type="text/javascript"
    +        src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
    +
    +<script type="text/javascript" src="cron/jquery-cron.js"></script>
    +
    +<link type="text/css" href="cron/jquery-cron.css" rel="stylesheet" />
    +
    +

    If used with useGentleSelect you'll also need:

    +
    +<script type="text/javascript" src="gentleSelect/jquery-gentleSelect.js"></script>
    +<link type="text/css" href="gentleSelect/jquery-gentleSelect.css" rel="stylesheet" />
    +
    +

    + then attach it to an empty <div> on DOM ready: +

    +
    +<script type="text/javascript">
    +$(document).ready(function() {
    +    $('#selector').cron(); // apply cron with default options
    +});
    +</script>
    +<!--- somewhere within <body> -->
    +<div id='selector'></div>
    +
    + +

    + There are several ways one can utilise the generated cron entry: +

      +
    1. + Interrogating the object : + See value method and onChange option. +
    2. + +
    3. + AJAX POST : + See the url_set option. +
    4. + +
    5. + embed in existing form (not recommended) : + The UI is rendered as a series of <select> boxes within the <div>. + Therefore, one can (in theory) embed the whole <div> within a form and on submission + interrogate the appropriate fields. The generated fiels will have the names: +
        +
      • cron-period : possible values are "minute, hour, day, week, month, year"
      • +
      • cron-mins : only relevant when cron-period = "hour"
      • +
      • cron-time-hour : only relevant when cron-period = "day, week, month, year"
      • +
      • cron-time-min : only relevant when cron-period = "day, week, month, year"
      • +
      • cron-dom : only relevant when cron-period = "month, year"
      • +
      • cron-month : only relevant when cron-period = "year"
      • +
      • cron-dow : only relevant when cron-period = "week"
      • +
      +
    6. +
    +

    + +

    Options

    + +

    initial

    +

    + The initial option allows you the set the initial cron value. If an initialll value is not set, + a default value of "* * * * *" is used. +

    + +

    + After the object has been set up, you can still update the value using + the value method. +

    + +

    url_set

    +

    + You can asynchronously submit the current value to you backend script by specifying then + the URL using the url_set option. +

    + +

    + If this option is set, a "save" icon will appear when changes are made allowing users + to submit their changes to the backend for processing. +

    + +

    + jquery-cron will submit the values {"cron": ??} using a POST request via AJAX. + If a non-error HTTP response is received, the save is considered to be successfule and + the "save" icon will be hidden until the next change is made. +

    + + +

    onChange

    +

    + You can set a callback function using the onChange option. The function will be called + each time the value changes. + For instance, the example in the introduction is implemented as using: +

    + +
    +$('#example1').cron({
    +    initial: "42 3 * * 5",
    +    onChange: function() {
    +        $('#example1-val').text($(this).cron("value"));
    +    }
    +});
    + +

    useGentleSelect

    +

    Tells the plugin to use gentleSelect to show dropdown options instead of the default select inputs. +

    + +
    +$('#example1').cron({
    +    initial: "42 3 * * 5",
    +    onChange: function() {
    +        $('#example1-val').text($(this).cron("value"));
    +    },
    +    useGentleSelect: true // default: false
    +});
    + +
    +
    +

    Generated cron entry:

    +
    + +

    effectOpts

    +

    + You can change the effects used when displaying/hiding the selection menu by changing the + parameters in effectOpts. These values will be used as the default options for gentleSelect. +

    + +

    + The following parameters can be set: +

    +

    + +

    + For example, the following uses the fade effect with a slower animation speed: +

    + +

    +

    +
    +$('#example2').cron({
    +    initial: "42 3 * * 5",
    +    effectOpts: {
    +        openEffect: "fade",
    +        openSpeed: "slow"
    +    }
    +});
    +

    + +

    Customising individual select boxes

    +

    + It is possible to customise each of the generated select boxes by sending additional + options to its instance of gentleSelect. + All attributes + support by jquery-gentleSelect can be specified. +

    + +

    + The following are the options to use for each select menu: +

      +
    • minuteOpts - Minutes past the hour (hourly)
    • +
    • timeMinuteOpts - Time:Minute (daily, weekly, monthly, yearly)
    • +
    • timeHourOpts - Time:Hour (daily, weekly, monthly, yearly)
    • +
    • dowOpts - Day of week (weekly)
    • +
    • domOpts - Day of month (monthly, yearly)
    • +
    • monthOpts - Month (yearly)
    • +
    +

    + +

    + For example, to change the title of the "Day of Month" select box which appears for monthly and yearly crons: +

    +$('#selector').cron({
    +    initial: "42 3 * * 5",
    +    domOpts: {
    +        title: "N-th day of the month"
    +    }
    +});
    +
    + +

    + +

    Adding custom values

    +

    + Additional entries can be included in the period selection using the customValues + option. This allows you to specify more complex cron entries that is not currently expressible + using the current setup. +

    +

    + For example, the following adds two additional entries to the selection: +

    +$('#selector').cron({
    +    initial: "*/5 * * * *",
    +    customValues: {
    +        "5 Minutes" : "*/5 * * * *",
    +        "2 Hours on Weekends" : "0 */2 * * 5,6"
    +    }
    +});
    +
    +

    + +
    +
    +

    Generated cron entry:

    +
    + +

    + Caveats: +

      +
    • + At present, cron entries specified in customValues are not validated. + It is down to the implementer to ensure that provided values are as required. +
    • +
    • + The value method can be used to retrieve + custom cron values. However, it cannot be used to set custom values. +
    • +
    +

    +

    Methods

    +

    value

    +

    + The value method enables you to set/get the current cron value. +

    + +
    +// Initialise a cron objecy
    +var cron_field = $('#selector').cron();
    +
    +// Updating the value of an existing cron object
    +cron_field.cron("value", "12 23 * * *");
    +
    +// calling the method with the extra argument returns the current value
    +var current_value = cron_field.cron("value")
    +
    + +
    + +Fork me on GitHub + + +