Package org.apache.karaf.scheduler.core

Source Code of org.apache.karaf.scheduler.core.QuartzScheduler

/*
* 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 org.apache.karaf.scheduler.core;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

import org.apache.karaf.scheduler.Job;
import org.apache.karaf.scheduler.ScheduleOptions;
import org.apache.karaf.scheduler.Scheduler;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.simpl.RAMJobStore;
import org.quartz.spi.ThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The quartz based implementation of the scheduler.
*
*/
public class QuartzScheduler implements Scheduler {

    /** Default logger. */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String PREFIX = "Apache Karaf Quartz Scheduler ";

    private static final String QUARTZ_SCHEDULER_NAME = "ApacheKaraf";

    /** Map key for the job object */
    static final String DATA_MAP_OBJECT = "QuartzJobScheduler.Object";

    /** Map key for the job name */
    static final String DATA_MAP_NAME = "QuartzJobScheduler.JobName";

    /** Map key for the scheduling options. */
    static final String DATA_MAP_OPTIONS = "QuartzJobScheduler.Options";

    /** Map key for the logger. */
    static final String DATA_MAP_LOGGER = "QuartzJobScheduler.Logger";

    /** The quartz scheduler. */
    private volatile org.quartz.Scheduler scheduler;

    public QuartzScheduler(ThreadPool threadPool) throws SchedulerException {
        // SLING-2261 Prevent Quartz from checking for updates
        System.setProperty("org.terracotta.quartz.skipUpdateCheck", Boolean.TRUE.toString());

        final DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance();
        // unique run id
        final String runID = new Date().toString().replace(' ', '_');
        factory.createScheduler(QUARTZ_SCHEDULER_NAME, runID, threadPool, new RAMJobStore());
        // quartz does not provide a way to get the scheduler by name AND runID, so we have to iterate!
        final Iterator<org.quartz.Scheduler> allSchedulersIter = factory.getAllSchedulers().iterator();
        while ( scheduler == null && allSchedulersIter.hasNext() ) {
            final org.quartz.Scheduler current = allSchedulersIter.next();
            if ( QUARTZ_SCHEDULER_NAME.equals(current.getSchedulerName())
                    && runID.equals(current.getSchedulerInstanceId()) ) {
                scheduler = current;
            }
        }
        if ( scheduler == null ) {
            throw new SchedulerException("Unable to find new scheduler with name " + QUARTZ_SCHEDULER_NAME + " and run ID " + runID);
        }

        scheduler.start();
        if ( this.logger.isDebugEnabled() ) {
            this.logger.debug(PREFIX + "started.");
        }
    }

    /**
     * Deactivate this component.
     * Stop the scheduler.
     */
    public void deactivate() {
        final org.quartz.Scheduler s = this.scheduler;
        this.scheduler = null;
        this.dispose(s);
    }

    /**
     * Dispose the quartz scheduler
     * @param s The scheduler.
     */
    private void dispose(final org.quartz.Scheduler s) {
        if ( s != null ) {
            try {
                s.shutdown();
            } catch (SchedulerException e) {
                this.logger.debug("Exception during shutdown of scheduler.", e);
            }
            if ( this.logger.isDebugEnabled() ) {
                this.logger.debug(PREFIX + "stopped.");
            }
        }
    }

    /**
     * Initialize the data map for the job executor.
     */
    private JobDataMap initDataMap(final String  jobName,
                                   final Object  job,
                                   final InternalScheduleOptions options) {
        final JobDataMap jobDataMap = new JobDataMap();

        jobDataMap.put(DATA_MAP_OBJECT, job);

        jobDataMap.put(DATA_MAP_NAME, jobName);
        jobDataMap.put(DATA_MAP_LOGGER, this.logger);
        jobDataMap.put(DATA_MAP_OPTIONS, options);

        return jobDataMap;
    }

    /**
     * Create the job detail.
     */
    private JobDetail createJobDetail(final String name,
                                      final JobDataMap jobDataMap,
                                      final boolean concurrent) {
        return JobBuilder.newJob((concurrent ? QuartzJobExecutor.class : NonParallelQuartzJobExecutor.class))
                .withIdentity(name)
                .usingJobData(jobDataMap)
                .build();
    }

    /**
     * Check the job object, either runnable or job is allowed
     */
    private void checkJob(final Object job)
            throws IllegalArgumentException {
        if (!(job instanceof Runnable) && !(job instanceof Job)) {
            throw new IllegalArgumentException("Job object is neither an instance of " + Runnable.class.getName() + " nor " + Job.class.getName());
        }
    }

    /** Used by the web console plugin. */
    org.quartz.Scheduler getScheduler() {
        return this.scheduler;
    }

    /**
     * @see org.apache.karaf.scheduler.Scheduler#NOW()
     */
    public ScheduleOptions NOW() {
        return AT(new Date());
    }

    /**
     * @see org.apache.karaf.scheduler.Scheduler#NOW(int, long)
     */
    public ScheduleOptions NOW(int times, long period) {
        return AT(new Date(), times, period);
    }

    /**
     * @see org.apache.karaf.scheduler.Scheduler#AT(java.util.Date)
     */
    public ScheduleOptions AT(Date date) {
        return new InternalScheduleOptions(date);
    }

    /**
     * @see org.apache.karaf.scheduler.Scheduler#AT(java.util.Date, int, long)
     */
    public ScheduleOptions AT(Date date, int times, long period) {
        return new InternalScheduleOptions(date, times, period);
    }

    /**
     * @see org.apache.karaf.scheduler.Scheduler#EXPR(java.lang.String)
     */
    public ScheduleOptions EXPR(String expression) {
        return new InternalScheduleOptions(expression);
    }

    /**
     * Schedule a job
     * @see org.apache.karaf.scheduler.Scheduler#schedule(java.lang.Object, org.apache.karaf.scheduler.ScheduleOptions)
     * @throws SchedulerException if the job can't be scheduled
     * @throws IllegalArgumentException If the preconditions are not met
     */
    public void schedule(final Object job, final ScheduleOptions options) throws IllegalArgumentException, SchedulerException {
        this.checkJob(job);

        if ( !(options instanceof InternalScheduleOptions)) {
            throw new IllegalArgumentException("Options has not been created via schedule or is null.");
        }
        final InternalScheduleOptions opts = (InternalScheduleOptions)options;

        if ( opts.argumentException != null ) {
            throw opts.argumentException;
        }

        // as this method might be called from unbind and during
        // unbind a deactivate could happen, we check the scheduler first
        final org.quartz.Scheduler s = this.scheduler;
        if ( s == null ) {
            throw new IllegalStateException("Scheduler is not available anymore.");
        }

        final String name;
        if ( opts.name != null ) {
            // if there is already a job with the name, remove it first
            try {
                final JobKey key = JobKey.jobKey(opts.name);
                final JobDetail jobdetail = s.getJobDetail(key);
                if (jobdetail != null) {
                    s.deleteJob(key);
                    this.logger.debug("Unscheduling job with name {}", opts.name);
                }
            } catch (final SchedulerException ignored) {
                // ignore
            }
            name = opts.name;
        } else {
            name = job.getClass().getName() + ':' + UUID.randomUUID();
            opts.name = name;
        }

        final Trigger trigger = opts.trigger.withIdentity(name).build();

        // create the data map
        final JobDataMap jobDataMap = this.initDataMap(name, job, opts);

        final JobDetail detail = this.createJobDetail(name, jobDataMap, opts.canRunConcurrently);

        this.logger.debug("Scheduling job {} with name {} and trigger {}", job, name, trigger);
        s.scheduleJob(detail, trigger);
    }

    /**
     * @see org.apache.karaf.scheduler.Scheduler#unschedule(java.lang.String)
     */
    public boolean unschedule(final String jobName) {
        final org.quartz.Scheduler s = this.scheduler;
        if ( jobName != null && s != null ) {
            try {
                final JobKey key = JobKey.jobKey(jobName);
                final JobDetail jobdetail = s.getJobDetail(key);
                if (jobdetail != null) {
                    s.deleteJob(key);
                    this.logger.debug("Unscheduling job with name {}", jobName);
                    return true;
                }
            } catch (final SchedulerException ignored) {
                // ignore
            }
        }
        return false;
    }

    @Override
    public Map<Object, ScheduleOptions> getJobs() throws SchedulerException {
        Map<Object, ScheduleOptions> jobs = new HashMap<>();
        org.quartz.Scheduler s = this.scheduler;
        if (s != null) {
            for (String group : s.getJobGroupNames()) {
                for (JobKey key : s.getJobKeys(GroupMatcher.jobGroupEquals(group))) {
                    JobDetail detail = s.getJobDetail(key);
                    ScheduleOptions options = (ScheduleOptions) detail.getJobDataMap().get(DATA_MAP_OPTIONS);
                    Object job = detail.getJobDataMap().get(DATA_MAP_OBJECT);
                    jobs.put(job, options);
                }
            }
        }
        return jobs;
    }

}
TOP

Related Classes of org.apache.karaf.scheduler.core.QuartzScheduler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.