package com.chickling.schedule; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.chickling.sqlite.ConnectionManager; import com.chickling.models.Auth; import com.chickling.models.MessageFactory; import com.chickling.bean.job.User; import com.chickling.util.StringUtil; import com.chickling.util.TimeUtil; import com.chickling.util.ScheduleCRUDUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.lang.reflect.Type; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import static org.quartz.JobBuilder.*; /** * Created by jw6v on 2015/11/27. */ public class ScheduleMgr { Logger log = LogManager.getLogger(ScheduleMgr.class); public void ScheduleMgr() {} public String initSchedule(){ /**Find out the schedule is triggered before service shut down or reboot**/ String query="SELECT `ScheduleID` FROM `Schedule` WHERE `ScheduleStatus`='1';"; int sid=0; try { PreparedStatement stat = ConnectionManager.getInstance().getConnection().prepareStatement(query); ResultSet rs=stat.executeQuery(); ArrayList<Integer> schedule=new ArrayList<>(); while(rs.next()){ schedule.add(rs.getInt("ScheduleID")); } stat.close(); /**Start schedule of Quartz**/ for(int id:schedule) { sid=id; startSchedule(id, ""); } } catch(Exception e) { log.error(e.getMessage()); return MessageFactory.rtnScheduleMessage("error", TimeUtil.getCurrentTime(), e.toString(), Integer.toString(sid)); } return MessageFactory.rtnScheduleMessage("success", TimeUtil.getCurrentTime(), "initiate quartz schedule is finished", ""); } public String startSchedule(int scheduleID,String token){ try { Type type = new TypeToken<Map>() { }.getType(); Gson gson = new Gson(); int scheduleOwner = 0; String scheduleInfo = ""; String currentTime = TimeUtil.getCurrentTime(); Date currentDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(currentTime); Auth au = new Auth(); User user = new User(); try { user = au.verify2(token); } catch (SQLException e) { e.printStackTrace(); } log.info("start"); try { if (!(token.equals(""))) { /**Triggering from user**/ if ( user.getPermission()==0 || !(user.getLogIN())) { return MessageFactory.rtnJobMessage("error", TimeUtil.getCurrentTime(), "Permission denied", ""); } else{ scheduleInfo = ScheduleCRUDUtils.getScheduleInfo(scheduleID, token); scheduleOwner = user.getUserID(); } } else { /**Initiating**/ String query = "SELECT `ScheduleOwner` from `Schedule_History` where `ScheduleID`=? and `ScheduleStatus`=1 order by `ScheduleStartTime` DESC limit 1;"; PreparedStatement stat = ConnectionManager.getInstance().getConnection().prepareStatement(query); stat.setInt(1, scheduleID); //log.info("Start schedule id: "+scheduleID); ResultSet rs = stat.executeQuery(); if(rs.next()){ scheduleOwner = rs.getInt("ScheduleOwner"); } //log.info("Start Schedule Owner: "+scheduleOwner); stat.close(); scheduleInfo = ScheduleCRUDUtils.getScheduleInfo(scheduleID); } } catch (Exception e) { log.error(e.getMessage()); return MessageFactory.rtnScheduleMessage("error", TimeUtil.getCurrentTime(), e.toString(), Integer.toString(scheduleID)); } Map info = gson.fromJson(scheduleInfo, type); if (((String) info.get("status")).equals("success")) { if (scheduleOwner <= 0) { scheduleOwner = (((Double) info.get("schedule_owner")).intValue()); } SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); /**Create Quartz scheduler by scheduleID and passed the value of scheduleID and scheduleOwner for maintaining scheduleInfo**/ JobDetail scheduler = newJob(ScheduleRunner.class) .withIdentity(Integer.toString(scheduleID), Integer.toString(scheduleID))//(,scheduleID) .usingJobData("ScheduleID", scheduleID) .usingJobData("ScheduleOwner", scheduleOwner) .build(); String mode = (String) info.get("schedule_mode"); String[] args = new String[2]; String croneformat = ""; sched.start(); if (!mode.equals("single")) { /**The schedule stat time is periodical**/ String startDateStr = (String) info.get("startwith"); Date startDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startDateStr); if (mode.equals("interval")) { args[0] = Integer.toString(((Double) info.get("every")).intValue()); args[1] = (String) info.get("unit"); } else { args[0] = Integer.toString(((Double) info.get("time")).intValue()); args[1] = Integer.toString(((Double) info.get("each")).intValue()); } /**Provide crone representing **/ croneformat = StringUtil.cronGenerator(mode, args,startDate); log.info(croneformat); if (startDate.before(currentDate)) { startDate = currentDate; } /**Crone trigger**/ Trigger trigger = TriggerBuilder.newTrigger() .withIdentity(Integer.toString(scheduleID), Integer.toString(scheduleID)) .withSchedule(CronScheduleBuilder.cronSchedule(croneformat).withMisfireHandlingInstructionFireAndProceed()) .startAt(startDate) .build(); sched.scheduleJob(scheduler, trigger); } else { /**The schedule start time is pinned on several calender time **/ Set<Trigger> triggerList = new HashSet<Trigger>(); ArrayList shcheduletime = (ArrayList) info.get("mod_set"); for (Object time : shcheduletime) { int i = 0; log.info("Starting schedule : " + scheduleID); Object[] s = ((Map) time).keySet().toArray(); Date startDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String) s[0]); log.info((String) s[0]); /**Only start the schedule which start time is after current time**/ if (startDate.after(currentDate)) { Trigger trigger = TriggerBuilder.newTrigger() .withIdentity((String) s[0], Integer.toString(scheduleID)) .startAt(startDate) .build(); log.info(startDate); /**Store trigger time in list**/ triggerList.add(trigger); } } Map<JobDetail, Set<? extends Trigger>> map = new HashMap<>(); map.put(scheduler, triggerList); sched.scheduleJobs(map, true); } try { /**Update Schedule info**/ ScheduleCRUDUtils.updateScheduleStatus(scheduleID, 1); ScheduleCRUDUtils.updateScheduleStartTime(scheduleID, TimeUtil.getCurrentTime()); } catch (SQLException e) { log.error(e.getMessage()); return MessageFactory.rtnScheduleMessage("error", TimeUtil.getCurrentTime(), "Update status failed, " + e.toString(), Integer.toString(scheduleID)); } return MessageFactory.rtnScheduleMessage("success", TimeUtil.getCurrentTime(), "", Integer.toString(scheduleID)); } else { /**Return error message from ScheduleCRUDUtils.getScheduleInfo**/ return scheduleInfo; } } catch(SchedulerException | ParseException e){ log.error(e.getMessage()); return MessageFactory.rtnScheduleMessage("error", TimeUtil.getCurrentTime(), "Update status failed, " + e.toString(), Integer.toString(scheduleID)); } } public String stopSchedule(int scheduleID, String token){ try { Auth au = new Auth(); ArrayList<Object> userInfo = au.verify(token); if (!(Boolean) userInfo.get(4) || userInfo.get(0).equals(0)) { return MessageFactory.rtnJobMessage("error", TimeUtil.getCurrentTime(), "Permission denied", ""); } else { Type type = new TypeToken<Map>() { }.getType(); Gson gson = new Gson(); SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); String scheduleInfo; ArrayList<TriggerKey> keyList = new ArrayList<>(); try { scheduleInfo = ScheduleCRUDUtils.getScheduleInfo(scheduleID, token); } catch (SQLException se) { log.error(se.getMessage()); return MessageFactory.rtnScheduleRunMessage("error", TimeUtil.getCurrentTime(), se.toString(), Integer.toString(scheduleID)); } Map info = gson.fromJson(scheduleInfo, type); String mode = (String) info.get("schedule_mode"); /**Stop and decline schedule by schedule ID**/ if (mode.equals("single")) { ArrayList shcheduletime = (ArrayList) info.get("mod_set"); for (Object time : shcheduletime) { Object[] s = ((Map) time).keySet().toArray(); keyList.add(TriggerKey.triggerKey((String) s[0], Integer.toString(scheduleID))); } } else { keyList.add(TriggerKey.triggerKey(Integer.toString(scheduleID), Integer.toString(scheduleID))); } sched.unscheduleJobs(keyList); try { ScheduleCRUDUtils.updateScheduleStatus(scheduleID, 0); } catch (SQLException se) { log.error(se.getMessage()); return MessageFactory.rtnScheduleMessage("error", TimeUtil.getCurrentTime(), se.toString(), Integer.toString(scheduleID)); } return MessageFactory.rtnScheduleMessage("success", TimeUtil.getCurrentTime(), "", Integer.toString(scheduleID)); } } catch(SchedulerException | SQLException sche){ return MessageFactory.rtnScheduleMessage("error", TimeUtil.getCurrentTime(), sche.toString(), Integer.toString(scheduleID)); } } }