001package com.thed.zblast.scheduler; 002 003import com.thed.model.AutomationJobDetail; 004import com.thed.model.AutomationJobScheduleDTO; 005import com.thed.zblast.util.RestUtil; 006import org.apache.commons.io.FilenameUtils; 007import org.apache.commons.io.monitor.FileAlterationListener; 008import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; 009import org.apache.commons.io.monitor.FileAlterationMonitor; 010import org.apache.commons.io.monitor.FileAlterationObserver; 011import org.w3c.dom.Document; 012import org.w3c.dom.Element; 013import org.w3c.dom.Node; 014import org.w3c.dom.NodeList; 015import org.xml.sax.SAXException; 016 017import javax.xml.parsers.DocumentBuilder; 018import javax.xml.parsers.DocumentBuilderFactory; 019import javax.xml.parsers.ParserConfigurationException; 020import javax.xml.xpath.XPath; 021import javax.xml.xpath.XPathConstants; 022import javax.xml.xpath.XPathExpressionException; 023import javax.xml.xpath.XPathFactory; 024import java.io.File; 025import java.io.IOException; 026import java.util.*; 027 028public class ScheduledJobExecutor { 029 030 private static final int POLL_INTERVAL = 500; 031 032 public static Integer getAutomationJobResultFilereadingMonitorWaitTime() { 033 034 return RestUtil.getAutomationJobResultFilereadingMonitorWaitTime(); 035 } 036 037 private Map<String, Map<String, Integer>> jobExecutionCounterMap = new HashMap<>(); 038 039 ////to track last file read time for this job 040 private Map<String, java.util.Date> jobExecutionLastFileReadTimer = new HashMap<>(); 041 042 public void executeJob(AutomationJobDetail automationJobDetail) { 043 044 List<AutomationJobScheduleDTO> automationJobScheduleDTOs; 045 try { 046 047 automationJobScheduleDTOs = RestUtil.createScheduleForSchduledJobs(automationJobDetail, "initialized"); 048 // not only status also update cycle and phase name with timestamp... 049 050 System.out.println("automationJobScheduleDTOs:::" + automationJobScheduleDTOs); 051 if (automationJobScheduleDTOs != null && !automationJobScheduleDTOs.isEmpty()) { 052 053 AutomationJobScheduleDTO dto = automationJobScheduleDTOs.get(0); 054 055 automationJobDetail.setScheduleId(dto.getId()); 056 057 System.out.println("automationJobDetail >>> " + automationJobDetail.getScheduleId()); 058 059 } 060 061 System.out.println("automationJobDetail:: " + automationJobDetail); 062 063 System.out.println("automationJobDetail.getScriptPath()::" + automationJobDetail.getScriptPath()); 064 jobExecutionCounterMap.put(automationJobDetail.getJobName(), new HashMap<>()); 065 066 System.out.println(Thread.currentThread().getName() + " 123| Kicking off the process..."); 067 068 StringBuilder command = new StringBuilder(automationJobDetail.getScriptPath()); 069 final Process process = Runtime.getRuntime().exec(command.toString()); 070 071 this.startListener(automationJobDetail); 072 073 int returnCode = process.waitFor(); 074 System.out.println("returnCode::::::::"+returnCode); 075 if (returnCode == 0) { 076 // pass 077 System.out.println("Pass.."); 078 079 //start file reader listener.. 080 081 }else { 082 083 //update zee for job failed.. 084 System.out.println("Failed script for job"); 085 086 RestUtil.updateZblastScheduleStatus(automationJobDetail.getScheduleId(), "job_failed_failed_to_execute_command",null, automationJobDetail); 087 088 } 089 090 } catch (IOException e) { 091 e.printStackTrace(); 092 } catch (InterruptedException e) { 093 e.printStackTrace(); 094 } catch (Exception e) { 095 e.printStackTrace(); 096 } 097 098 } 099 100 101 102 private void startListener(AutomationJobDetail automationJobDetail) throws Exception { 103 ScheduledJobExecutor scheduledJobExecutor = new ScheduledJobExecutor(); 104 105 FileAlterationObserver observer = new FileAlterationObserver( automationJobDetail.getResultPath()); 106 107 FileAlterationMonitor monitor = new FileAlterationMonitor(POLL_INTERVAL); 108 FileAlterationListener listener = new FileAlterationListenerAdaptor() { 109 @Override 110 public void onFileCreate(File file) { 111 System.out.println(""" 112 File: %s created""".formatted(file.getName())); 113 //to track last file read time for this job 114 115 String ext = FilenameUtils.getExtension(file.getName()); 116 117 System.out.println("ext:::"+ext); 118 119 if(ext.equalsIgnoreCase("xml")) 120 { 121 System.out.println("Inside xml file +"+file.getName()); 122 JobProgressDTO jobProgressDTO = getProgressResultFromFile(file); 123 scheduledJobExecutor.postProgressDetails(automationJobDetail,jobProgressDTO); 124 jobExecutionLastFileReadTimer.put(automationJobDetail.getJobName(), new java.util.Date()); 125 } 126 } 127 128 @Override 129 public void onFileDelete(File file) { 130 System.out.println(""" 131 File: %s deleted""".formatted(file.getName())); 132 } 133 134 @Override 135 public void onFileChange(File file) { 136 System.out.println(""" 137 File: %s changed""".formatted(file.getName())); 138 } 139 }; 140 observer.addListener(listener); 141 monitor.addObserver(observer); 142 monitor.start(); 143 144 //monitor and stop the job after certain interval 145 Timer time = new Timer(); // Instantiate Timer Object 146 ScheduledTask st = new ScheduledTask(monitor, automationJobDetail); // Instantiate SheduledTask class 147 time.schedule(st, 0, 60000); // Create Repetitively task for every 30 secs 148 149 150 } 151 152 //Scheduler to check and kill the monitoring of file after last file read interval 153 public class ScheduledTask extends TimerTask { 154 155 Date now; // to display current time 156 FileAlterationMonitor monitor = null; 157 AutomationJobDetail automationJobDetail = null; 158 159 ScheduledTask(FileAlterationMonitor monitor, AutomationJobDetail automationJobDetail){ 160 161 this.monitor = monitor; 162 this.automationJobDetail = automationJobDetail; 163 } 164 165 166 public void run() { 167 now = new Date(); // initialize date 168 System.out.println("Time is :" + now); // Display current time 169 Date lastReadTime = jobExecutionLastFileReadTimer.get(automationJobDetail.getJobName()); 170 171 if(lastReadTime == null) { 172 lastReadTime = new Date(); 173 } 174 175 long diff = new Date().getTime() - lastReadTime.getTime(); 176 177 long minutes = diff / (60 * 1000) % 60; 178 179 System.out.println("minutes diff::"+minutes); 180 181 if( minutes > getAutomationJobResultFilereadingMonitorWaitTime()) { // stop the job after last file read -- wait for configured time. 182 183 try { 184 System.out.println("Stoping the job:"+automationJobDetail); 185 monitor.stop(); 186 //cleanup tasks.. 187 jobExecutionCounterMap.put(automationJobDetail.getJobName(), null); 188 189 //set job to new so that result processor picks the job 190 RestUtil.updateZblastScheduleStatus(automationJobDetail.getScheduleId(), "new", null, automationJobDetail); 191 192 this.cancel(); 193 194 } catch (Exception e) { 195 e.printStackTrace(); 196 } 197 } 198 199 } 200 } 201 202 private JobProgressDTO getProgressResultFromFile(File resultFile) { 203 204 JobProgressDTO progressDTO = new JobProgressDTO(); 205 206 try { 207 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 208 DocumentBuilder dBuilder; 209 210 dBuilder = dbFactory.newDocumentBuilder(); 211 212 Document doc = dBuilder.parse(resultFile); 213 doc.getDocumentElement().normalize(); 214 215 XPath xPath = XPathFactory.newInstance().newXPath(); 216 217 String expression = "testsuite"; 218 NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET); 219 220 for (int i = 0; i < nodeList.getLength(); i++) { 221 Node nNode = nodeList.item(i); 222 System.out.println("\nCurrent Element :" + nNode.getNodeName()); 223 224 if (nNode.getNodeType() == Node.ELEMENT_NODE) { 225 Element eElement = (Element) nNode; 226 System.out.println("tests :" + eElement.getAttribute("tests")); 227 System.out.println("failures :" + eElement.getAttribute("failures")); 228 System.out.println("errors :" + eElement.getAttribute("errors")); 229 System.out.println("skipped :" + eElement.getAttribute("skipped")); 230 231 progressDTO.setErrorCount(Integer.valueOf(eElement.getAttribute("errors").trim()).intValue()); 232 progressDTO.setExecutedCount(Integer.valueOf(eElement.getAttribute("tests").trim()).intValue()); 233 progressDTO.setFailedCount(Integer.valueOf(eElement.getAttribute("failures").trim()).intValue()); 234 progressDTO.setSkippedCount(Integer.valueOf(eElement.getAttribute("skipped").trim()).intValue()); 235 236 } 237 } 238 } catch (ParserConfigurationException e) { 239 e.printStackTrace(); 240 } catch (SAXException e) { 241 e.printStackTrace(); 242 } catch (IOException e) { 243 e.printStackTrace(); 244 } catch (XPathExpressionException e) { 245 e.printStackTrace(); 246 } 247 System.out.println("Before returning progressDTO::"+progressDTO); 248 return progressDTO; 249 250 } 251 252 253 public void postProgressDetails(AutomationJobDetail automationJobDetail, JobProgressDTO jobProgressDTO) { 254 255 try { 256 257 System.out.println("In postProgressDetails jobProgressDTO::"+jobProgressDTO); 258 259 Map<String, Integer> thisJobExecutionCounterMap = jobExecutionCounterMap.get(automationJobDetail.getJobName()); 260 261 System.out.println("thisJobExecutionCounterMap::::"+thisJobExecutionCounterMap); 262 263 if(thisJobExecutionCounterMap == null) { 264 265 thisJobExecutionCounterMap = new HashMap<>(); 266 } 267 268 if (thisJobExecutionCounterMap.containsKey("tests")) { 269 thisJobExecutionCounterMap.put("tests", thisJobExecutionCounterMap.get("tests")+jobProgressDTO.getExecutedCount()); 270 } else { 271 thisJobExecutionCounterMap.put("tests", jobProgressDTO.getExecutedCount()); 272 273 } 274 if (thisJobExecutionCounterMap.containsKey("failures")) { 275 thisJobExecutionCounterMap.put("failures", thisJobExecutionCounterMap.get("failures")+jobProgressDTO.getFailedCount()); 276 } else { 277 thisJobExecutionCounterMap.put("failures", jobProgressDTO.getFailedCount()); 278 279 } 280 281 if (thisJobExecutionCounterMap.containsKey("skipped")) { 282 thisJobExecutionCounterMap.put("skipped", thisJobExecutionCounterMap.get("skipped")+jobProgressDTO.getSkippedCount()); 283 } else { 284 thisJobExecutionCounterMap.put("skipped", jobProgressDTO.getSkippedCount()); 285 286 } 287 288 if (thisJobExecutionCounterMap.containsKey("errors")) { 289 thisJobExecutionCounterMap.put("errors", thisJobExecutionCounterMap.get("errors")+jobProgressDTO.getErrorCount()); 290 } else { 291 thisJobExecutionCounterMap.put("errors", jobProgressDTO.getErrorCount()); 292 293 } 294 295 System.out.println("thisJobExecutionCounterMap :::"+thisJobExecutionCounterMap); 296 297 298 jobExecutionCounterMap.put(automationJobDetail.getJobName(), thisJobExecutionCounterMap); 299 300 JobProgressDTO dto = new JobProgressDTO(); 301 302 dto.setErrorCount(thisJobExecutionCounterMap.get("errors")); 303 dto.setExecutedCount(thisJobExecutionCounterMap.get("tests")); 304 dto.setFailedCount(thisJobExecutionCounterMap.get("failures")); 305 dto.setSkippedCount(thisJobExecutionCounterMap.get("skipped")); 306 dto.setJobName(automationJobDetail.getJobName()); 307 dto.setSchedulerId(automationJobDetail.getScheduleId()); 308 309 System.out.println("postProgressDetails ::: " + dto); 310 311 312 RestUtil.postProgressDetails(dto); 313 } catch (IOException e) { 314 e.printStackTrace(); 315 } 316 } 317 318 /** 319 * if (testExecutionCounterMap.containsKey(key)) { 320 * testExecutionCounterMap.put(key, testExecutionCounterMap.get(key) + (new 321 * Integer(value))); } else { testExecutionCounterMap.put(key, new 322 * Integer(value)); } 323 */ 324 325}