/* * RED5 Open Source Flash Server - http://code.google.com/p/red5/ * * Copyright 2006-2012 by respective authors (see below). All rights reserved. * * Licensed 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 org.red5.server.scheduling; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicLong; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; import org.red5.logging.Red5LoggerFactory; import org.red5.server.api.scheduling.IScheduledJob; import org.red5.server.api.scheduling.ISchedulingService; import org.red5.server.jmx.mxbeans.QuartzSchedulingServiceMXBean; import org.slf4j.Logger; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.jmx.export.annotation.ManagedResource; /** * Scheduling service that uses Quartz as backend. * * @author The Red5 Project (red5@osflash.org) * @author Joachim Bauch (jojo@struktur.de) * @author Paul Gregoire (mondain@gmail.com) */ @ManagedResource(objectName = "org.red5.server:name=schedulingService,type=QuartzSchedulingService") public class QuartzSchedulingService implements ISchedulingService, QuartzSchedulingServiceMXBean, InitializingBean, DisposableBean { private static Logger log = Red5LoggerFactory.getLogger(QuartzSchedulingService.class); /** * Number of job details */ protected AtomicLong jobDetailCounter = new AtomicLong(0); /** * Creates schedulers. */ protected SchedulerFactory factory; /** * Service scheduler */ protected Scheduler scheduler; /** * Instance id */ protected String instanceId; /** Constructs a new QuartzSchedulingService. */ public void afterPropertiesSet() throws Exception { log.debug("Initializing..."); try { //create the standard factory if we dont have one if (factory == null) { factory = new StdSchedulerFactory(); } if (instanceId == null) { scheduler = factory.getScheduler(); } else { scheduler = factory.getScheduler(instanceId); } //start the scheduler if (scheduler != null) { scheduler.start(); } else { log.error("Scheduler was not started"); } } catch (SchedulerException ex) { throw new RuntimeException(ex); } } public void setFactory(SchedulerFactory factory) { this.factory = factory; } public void setInstanceId(String instanceId) { this.instanceId = instanceId; } // protected void registerJMX() { // //register with jmx server // MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); // try { // ObjectName oName = null; // if (instanceId == null) { // oName = new ObjectName("org.red5.server:name=" + this.getClass().getName()); // } else { // oName = new ObjectName("org.red5.server:name=" + this.getClass().getName() + ",instanceId=" + instanceId); // } // mbeanServer.registerMBean(this, oName); // } catch (Exception e) { // log.warn("Error on jmx registration", e); // } // } /** {@inheritDoc} */ public String addScheduledJob(int interval, IScheduledJob job) { String result = getJobName(); // Create trigger that fires indefinitely every <interval> milliseconds SimpleTrigger trigger = new SimpleTrigger("Trigger_" + result, null, new Date(), null, SimpleTrigger.REPEAT_INDEFINITELY, interval); scheduleJob(result, trigger, job); return result; } /** {@inheritDoc} */ public String addScheduledOnceJob(Date date, IScheduledJob job) { String result = getJobName(); // Create trigger that fires once at <date> SimpleTrigger trigger = new SimpleTrigger("Trigger_" + result, null, date); scheduleJob(result, trigger, job); return result; } /** {@inheritDoc} */ public String addScheduledOnceJob(long timeDelta, IScheduledJob job) { // Create trigger that fires once in <timeDelta> milliseconds return addScheduledOnceJob(new Date(System.currentTimeMillis() + timeDelta), job); } /** {@inheritDoc} */ public String addScheduledJobAfterDelay(int interval, IScheduledJob job, int delay) { String result = getJobName(); // Initialize the start time to now and add the delay. long startTime = System.currentTimeMillis() + delay; // Create trigger that fires indefinitely every <internval> milliseconds. SimpleTrigger trigger = new SimpleTrigger("Trigger_" + result, null, new Date(startTime), null, SimpleTrigger.REPEAT_INDEFINITELY, interval); // Schedule the job with Quartz. scheduleJob(result, trigger, job); // Return the job name. return result; } /** * Getter for job name. * * @return Job name */ public String getJobName() { String result = "ScheduledJob_" + jobDetailCounter.getAndIncrement(); return result; } /** {@inheritDoc} */ public List<String> getScheduledJobNames() { List<String> result = new ArrayList<String>(); if (scheduler != null) { try { for (String name : scheduler.getJobNames(null)) { result.add(name); } } catch (SchedulerException ex) { throw new RuntimeException(ex); } } else { log.warn("No scheduler is available"); } return result; } /** {@inheritDoc} */ public void pauseScheduledJob(String name) { try { scheduler.pauseJob(name, null); } catch (SchedulerException ex) { throw new RuntimeException(ex); } } /** {@inheritDoc} */ public void resumeScheduledJob(String name) { try { scheduler.resumeJob(name, null); } catch (SchedulerException ex) { throw new RuntimeException(ex); } } public void pauseScheduledTrigger(String name) { try { scheduler.pauseTrigger("Trigger_" + name, null); } catch (SchedulerException ex) { throw new RuntimeException(ex); } } public void resumeScheduledTrigger(String name) { try { scheduler.resumeTrigger("Trigger_" + name, null); } catch (SchedulerException ex) { throw new RuntimeException(ex); } } /** {@inheritDoc} */ public void removeScheduledJob(String name) { try { scheduler.deleteJob(name, null); } catch (SchedulerException ex) { throw new RuntimeException(ex); } } /** * Schedules job * @param name Job name * @param trigger Job trigger * @param job Scheduled job object * * @see org.red5.server.api.scheduling.IScheduledJob */ private void scheduleJob(String name, Trigger trigger, IScheduledJob job) { if (scheduler != null) { // Store reference to applications job and service JobDetail jobDetail = new JobDetail(name, null, QuartzSchedulingServiceJob.class); jobDetail.getJobDataMap().put(QuartzSchedulingServiceJob.SCHEDULING_SERVICE, this); jobDetail.getJobDataMap().put(QuartzSchedulingServiceJob.SCHEDULED_JOB, job); try { scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException ex) { throw new RuntimeException(ex); } } else { log.warn("No scheduler is available"); } } public void destroy() throws Exception { if (scheduler != null) { log.debug("Destroying..."); scheduler.shutdown(); } } }