FixedRateTask.java :  » Inversion-of-Control » carbon » org » sape » carbon » services » scheduler » Java Open Source

Java Open Source » Inversion of Control » carbon 
carbon » org » sape » carbon » services » scheduler » FixedRateTask.java
/*
 * The contents of this file are subject to the Sapient Public License
 * Version 1.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://carbon.sf.net/License.html.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is The Carbon Component Framework.
 *
 * The Initial Developer of the Original Code is Sapient Corporation
 *
 * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
 */

package org.sape.carbon.services.scheduler;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;

import org.sape.carbon.core.config.InvalidConfigurationException;
import org.sape.carbon.core.util.calendar.DayOfWeekEnum;
import org.sape.carbon.core.util.calendar.MonthEnum;

import org.sape.carbon.services.threadpool.ThreadPool;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Utility class used to interperet FixedRateTaskConfiguration and
 * schedule fixed rate tasks.
 *
 * Copyright 2002 Sapient
 * @since carbon 1.0
 * @author Douglas Voet, June 2002
 * @version $Revision: 1.16 $($Author: dvoet $ / $Date: 2003/11/20 21:46:15 $)
 */
class FixedRateTask extends AbstractTask {

    /**
     * Provides a handle to Apache-commons logger
     */
    private Log log = LogFactory.getLog(this.getClass());

    // constants specifying the range of valid configuration values
    /** Mininum valid minute value. */
    private static final int MIN_MINUTE = 0;
    /** Maximum valid minute value. */
    private static final int MAX_MINUTE = 59;

    /** Mininum valid hour value. */
    private static final int MIN_HOUR = 0;
    /** Maximum valid hour value. */
    private static final int MAX_HOUR = 23;

    /** Mininum valid day of month value. */
    private static final int MIN_DAY_OF_MONTH = 1;
    /** Maximum valid day of month value. */
    private static final int MAX_DAY_OF_MONTH = 31;

    // constants used to set the appropriate period for task execution
    /** Milliseconds for one minute. */
    private static final long EVERY_MINUTE = 1000 * 60;
    /** Milliseconds for one hour. */
    private static final long EVERY_HOUR = EVERY_MINUTE * 60;
    /** Milliseconds for one day. */
    private static final long EVERY_DAY = EVERY_HOUR * 24;
    /** Milliseconds for one week. */
    private static final long EVERY_WEEK = EVERY_DAY * 7;
    /** Milliseconds for one month. */
    private static final long EVERY_MONTH = EVERY_DAY * 30;
    /** Milliseconds for one year. */
    private static final long EVERY_YEAR = EVERY_DAY * 365;

    /** Holds the period of how often the task will execute. */
    private long period;

    /** Holds the first run time of the task. */
    private Date time;

    /**
     * This constructor determines the starting time and date and the repeat
     * period of the task.  See the class javadoc for FixedRateTaskConfiguration
     * for valid configuration and related behavior.
     *
     * @see org.sape.carbon.services.scheduler.FixedRateTaskConfiguration
     *
     * @param taskConfiguration
     */
    protected FixedRateTask(
        FixedRateTaskConfiguration taskConfiguration,
        ThreadPool threadPool) {
            
        super(taskConfiguration, threadPool);

        Integer minute = taskConfiguration.getMinute();
        Integer hour = taskConfiguration.getHour();
        Integer dayOfMonth = taskConfiguration.getDayOfMonth();
        MonthEnum month = taskConfiguration.getMonth();
        DayOfWeekEnum dayOfWeek = taskConfiguration.getDayOfWeek();

        //validate configuration information is in the right range
        validate(
            taskConfiguration.getConfigurationName(),
            "Minute",
            minute,
            MIN_MINUTE,
            MAX_MINUTE);
        validate(
            taskConfiguration.getConfigurationName(),
            "Hour",
            hour,
            MIN_HOUR,
            MAX_HOUR);
        validate(
            taskConfiguration.getConfigurationName(),
            "DayOfMonth",
            dayOfMonth,
            MIN_DAY_OF_MONTH,
            MAX_DAY_OF_MONTH);

        Calendar firstRunTime = new GregorianCalendar();
        firstRunTime.set(Calendar.MILLISECOND, 0);
        firstRunTime.set(Calendar.SECOND, 0);

        // this section of if statements determines when the task should
        // execute first and how often it should execute after that
        if (minute == null) {
            // task runs every minute starting at the next minute

            // make sure there is not extra configuration specified
            if (!(hour == null && dayOfMonth == null
                    && month == null && dayOfWeek == null)) {

                throw new InvalidConfigurationException(
                    this.getClass(),
                    taskConfiguration.getConfigurationName(),
                    "Minute",
                    "Minute was not specifed, but other configuration "
                        + "information exists.  Either specify Minute "
                        + "or remove all other configuration information");
            }

            // run task every minute starting with the next minute
            this.period = EVERY_MINUTE;

            // start running at the next minute
            firstRunTime.add(Calendar.MINUTE, 1);

        } else if (hour == null) {
            // task runs every hour starting at the next occurence of the
            // specified minute

            // make sure there is not extra configuration specified
            if (!(dayOfMonth == null && month == null && dayOfWeek == null)) {
                throw new InvalidConfigurationException(
                    this.getClass(),
                    taskConfiguration.getConfigurationName(),
                    "Hour",
                    "Hour was not specifed, but day and/or month "
                        + "configuration information exists.  Either "
                        + "specify Hour or remove day and month "
                        + "configuration information");
            }

            // run task every hour starting with the next hour
            this.period = EVERY_HOUR;

            firstRunTime.set(Calendar.MINUTE, minute.intValue());

            Date now = new Date();
            if (firstRunTime.getTime().compareTo(now) <= 0) {
                firstRunTime.add(Calendar.HOUR_OF_DAY, 1);
            }

        } else if (dayOfMonth == null && dayOfWeek == null) {
            // task runs every day starting at the next occurence
            // of the specified hour and minute

            // make sure there is not extra configuration specified
            if (month != null) {
                throw new InvalidConfigurationException(
                    this.getClass(),
                    taskConfiguration.getConfigurationName(),
                    "Month",
                    "Month was supplied without DayOfMonth, either remove "
                        + "Month or add DayOfMonth");
            }

            this.period = EVERY_DAY;

            firstRunTime.set(Calendar.MINUTE, minute.intValue());
            firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());

            Date now = new Date();
            if (firstRunTime.getTime().compareTo(now) <= 0) {
                // starting tomorrow if the scheduled
                // time of day has passed today
                firstRunTime.add(Calendar.DAY_OF_MONTH, 1);
            }

        } else if (dayOfMonth != null) {
            // make sure there is not extra configuration specified
            if (dayOfWeek != null) {
                throw new InvalidConfigurationException(
                    this.getClass(),
                    taskConfiguration.getConfigurationName(),
                    "DayOfWeek",
                    "Both DayOfWeek and DayOfMonth were specified, only one "
                        + "can be used");
            }

            if (month == null) {
                // run task every month starting next month if the scheduled
                // date and time has passed this month

                this.period = EVERY_MONTH;

                firstRunTime.set(Calendar.MINUTE, minute.intValue());
                firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
                firstRunTime.set(Calendar.DAY_OF_MONTH, dayOfMonth.intValue());

                Date now = new Date();
                if (firstRunTime.getTime().compareTo(now) <= 0) {
                    firstRunTime.add(Calendar.MONTH, 1);
                }

            } else {
                // run task every year starting next year if the scheduled
                // date and time has passed this year

                this.period = EVERY_YEAR;

                firstRunTime.set(Calendar.MINUTE, minute.intValue());
                firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
                firstRunTime.set(Calendar.DAY_OF_MONTH, dayOfMonth.intValue());
                firstRunTime.set(Calendar.MONTH, month.getOrdinal());

                Date now = new Date();
                if (firstRunTime.getTime().compareTo(now) <= 0) {
                    firstRunTime.add(Calendar.YEAR, 1);
                }
            }

        } else if (dayOfWeek != null) {
            // run task every week starting next week if the scheduled
            // day and time has passed this week

            // make sure there is not extra configuration specified
            if (month != null) {
                throw new InvalidConfigurationException(
                    this.getClass(),
                    taskConfiguration.getConfigurationName(),
                    "Month",
                    "Month cannot be used with DayOfWeek, "
                        + "it can only be used in conjunction with "
                        + "DayOfMonth");
            }

            this.period = EVERY_WEEK;

            firstRunTime.set(Calendar.MINUTE, minute.intValue());
            firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
            firstRunTime.set(Calendar.DAY_OF_WEEK, dayOfWeek.getOrdinal());

            Date now = new Date();
            if (firstRunTime.getTime().compareTo(now) <= 0) {
                firstRunTime.add(Calendar.WEEK_OF_MONTH, 1);
            }

        } else {
            // I don't think this can ever happen
            throw new InvalidConfigurationException(
                this.getClass(),
                taskConfiguration.getConfigurationName(),
                "all attributes",
                "Could not determine first run time or repeat period");
        }

        this.time = firstRunTime.getTime();

        if (log.isTraceEnabled()) {
            log.trace("Creating task defined by configuration ["
                + taskConfiguration.getConfigurationName()
                + "] to run starting at ["
                + this.time
                + "] with period ["
                + this.period
                + "] ms");
        }

    }

    /**
     * @see AbstractTask#schedule(Timer)
     */
    public void schedule(Timer timer) {
        timer.scheduleAtFixedRate(getTask(), this.time, this.period);
    }

    /**
     * Checks to make sure that value is within min and max values
     *
     * @param configName configuration the value being validated comes from
     * @param attributeName name of attribute being validated
     * @param value the value of the attribute
     * @param minValue the minimum valid value
     * @param maxValue the maximum valid value
     */
    private void validate(String configName,
        String attributeName,
        Integer value,
        int minValue,
        int maxValue) {

        if (value != null
                && !isWithinRange(value.intValue(), minValue, maxValue)) {

            throw new InvalidConfigurationException(
                this.getClass(),
                configName,
                attributeName,
                "Value ["
                    + value
                    + "] out of range: min ["
                    + minValue
                    + "], max ["
                    + maxValue
                    + "] inclusive");
        }
    }

    /**
     * Checks if a value is in given range.
     *
     * @param value the value to check
     * @param min the mininum the value should be
     * @param max the maximum the value should be
     * @return if the value is with the range
     */
    private boolean isWithinRange(int value, int min, int max) {
        if (value < min || value > max) {
            return false;
        } else {
            return true;
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.