/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ro.nextreports.server.service; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.joda.time.DateTime; import org.joda.time.Seconds; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerKey; import org.springframework.beans.factory.annotation.Required; import org.springframework.security.access.annotation.Secured; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.transaction.annotation.Transactional; import ro.nextreports.server.StorageConstants; import ro.nextreports.server.domain.Entity; import ro.nextreports.server.domain.ReportJobInfo; import ro.nextreports.server.domain.RunReportHistory; import ro.nextreports.server.domain.SchedulerJob; import ro.nextreports.server.domain.User; import ro.nextreports.server.exception.NotFoundException; import ro.nextreports.server.schedule.RunReportJob; import ro.nextreports.server.schedule.ScheduleConstants; import ro.nextreports.server.util.QuartzUtil; /** * Created by IntelliJ IDEA. * User: mihai.panaitescu * Date: May 21, 2008 * Time: 1:34:31 PM */ public class DefaultSchedulerService implements SchedulerService { private StorageService storageService; private Scheduler scheduler; @Required public void setStorageService(StorageService storageService) { this.storageService = storageService; } @Required public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } @Transactional(readOnly = true) @Secured("AFTER_ACL_COLLECTION_READ") public SchedulerJob[] getSchedulerJobs() { Entity[] entities = new Entity[0]; try { entities = storageService.getEntitiesByClassName(StorageConstants.SCHEDULER_ROOT, SchedulerJob.class.getName()); } catch (NotFoundException e) { // never happening throw new RuntimeException(e); } SchedulerJob[] schedulerJobs = new SchedulerJob[entities.length]; System.arraycopy(entities, 0, schedulerJobs, 0, entities.length); return schedulerJobs; } @Transactional(readOnly = true) @Secured("AFTER_ACL_COLLECTION_READ") public SchedulerJob[] getActiveSchedulerJobs() { List<SchedulerJob> activeJobs = new ArrayList<SchedulerJob>(); SchedulerJob[] schedulerJobs = getSchedulerJobs(); for (SchedulerJob job : schedulerJobs) { boolean active = false; Date now = new Date(); if (ScheduleConstants.ONCE_TYPE.equals(job.getTime().getType())) { active = (job.getTime().getRunDate().compareTo(now) >= 0) || job.isRunning(); } else { active = ((job.getTime().getStartActivationDate().compareTo(now) <= 0) && (job.getTime().getEndActivationDate().compareTo(now) >= 0)) || job.isRunning(); } if (active) { activeJobs.add(job); Map<String, JobExecutionContext> runningJobs; try { runningJobs = QuartzUtil.getRunningJobs(scheduler); } catch (SchedulerException e) { throw new RuntimeException(e); } JobExecutionContext executionContext = runningJobs.get(job.getPath()); if (executionContext != null) { Date fireTime = executionContext.getFireTime(); job.setRunTime(Seconds.secondsBetween(new DateTime(fireTime), new DateTime()).getSeconds()); } } } schedulerJobs = activeJobs.toArray(new SchedulerJob[activeJobs.size()]); return schedulerJobs; } public JobDetail getJobDetail(SchedulerJob schedulerJob) { try { List<JobDetail> jobs = QuartzUtil.getAllJobDetails(scheduler); for (JobDetail job : jobs) { //System.out.println("*** jobName=" + job.getName() + " name=" + schedulerJob.getPath()); if (job.getKey().getName().equals(schedulerJob.getPath())) { return job; } } } catch (SchedulerException e) { throw new RuntimeException(e); } return null; } public ReportJobInfo[] getReportJobInfos() { User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); List<JobDetail> jobs; List<Trigger> triggers; Map<String, JobExecutionContext> runningJobs; try { jobs = QuartzUtil.getAllJobDetails(scheduler); triggers = QuartzUtil.getAllTriggers(scheduler); runningJobs = QuartzUtil.getRunningJobs(scheduler); } catch (SchedulerException e) { throw new RuntimeException(e); } List<ReportJobInfo> jobInfos = new ArrayList<ReportJobInfo>(triggers.size()); for (JobDetail job : jobs) { if (!isJobOfUser(job, user)) { continue; } ReportJobInfo jobInfo = new ReportJobInfo(); String jobName = job.getKey().getName(); jobInfo.setJobName(jobName); jobInfo.setRunner(getUser(job).getUsername()); jobInfo.setRunnerKey((String) job.getJobDataMap().get(RunReportJob.RUNNER_KEY)); jobInfo.setReportType((String) job.getJobDataMap().get(RunReportJob.REPORT_TYPE)); if (runningJobs.containsKey(jobName)) { jobInfo.setRunning(true); JobExecutionContext executionContext = runningJobs.get(jobName); Date fireTime = executionContext.getFireTime(); jobInfo.setRunTime(Seconds.secondsBetween(new DateTime(fireTime), new DateTime()).getSeconds()); jobInfo.setNextRun(executionContext.getNextFireTime()); jobInfo.setStartDate(fireTime); } else { Trigger trigger; try { TriggerKey triggerKey = new TriggerKey(job.getKey().getName(), job.getKey().getGroup()); trigger = scheduler.getTrigger(triggerKey); } catch (SchedulerException e) { throw new RuntimeException(e); } // a report runned with Run action can have the trigger null if we enter the dashboard if (trigger != null) { jobInfo.setNextRun(trigger.getNextFireTime()); } } jobInfos.add(jobInfo); } return jobInfos.toArray(new ReportJobInfo[jobInfos.size()]); } private boolean isJobOfUser(JobDetail job, User user) { if (!RunReportHistory.USER.equals(job.getJobDataMap().getString(RunReportJob.RUNNER_TYPE))) { return false; } if (user.isAdmin()) { return true; } if (user.getId().equals(job.getJobDataMap().getString(RunReportJob.RUNNER_ID))) { return true; } return false; } public User getUser(JobDetail job) { try { return (User) storageService.getEntityById(job.getJobDataMap().getString(RunReportJob.RUNNER_ID)); } catch (NotFoundException e) { // TODO e.printStackTrace(); return null; } } }