Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 72908 invoked from network); 3 Sep 2003 16:23:10 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 3 Sep 2003 16:23:10 -0000 Received: (qmail 54081 invoked by uid 500); 3 Sep 2003 16:04:06 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 53879 invoked by uid 500); 3 Sep 2003 16:04:03 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 53728 invoked by uid 500); 3 Sep 2003 16:04:01 -0000 Delivered-To: apmail-cocoon-2.1-cvs@apache.org Received: (qmail 53589 invoked from network); 3 Sep 2003 16:03:59 -0000 Received: from unknown (HELO minotaur.apache.org) (209.237.227.194) by daedalus.apache.org with SMTP; 3 Sep 2003 16:03:58 -0000 Received: (qmail 57919 invoked by uid 1041); 3 Sep 2003 16:04:02 -0000 Date: 3 Sep 2003 16:04:02 -0000 Message-ID: <20030903160402.57918.qmail@minotaur.apache.org> From: giacomo@apache.org To: cocoon-2.1-cvs@apache.org Subject: cvs commit: cocoon-2.1/src/blocks/cron/samples cron.xsp docs.xml samples.xml sitemap.xmap X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N giacomo 2003/09/03 09:04:02 Modified: . blocks.properties gump.xml lib jars.xml Added: src/blocks/cron/conf cron-category.xlog cron-target.xlog cron.xconf cron.xsamples src/blocks/cron/java/org/apache/cocoon/components/cron ConfigurableCronJob.java CronJob.java JobScheduler.java QuartzJobExecutor.java QuartzJobScheduler.java TestCronJob.java src/blocks/cron/lib quartz-1.0.7.jar src/blocks/cron/samples cron.xsp docs.xml samples.xml sitemap.xmap Log: added JobScheduler block Revision Changes Path 1.26 +1 -0 cocoon-2.1/blocks.properties Index: blocks.properties =================================================================== RCS file: /home/cvs/cocoon-2.1/blocks.properties,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -b -u -r1.25 -r1.26 --- blocks.properties 7 Aug 2003 08:56:39 -0000 1.25 +++ blocks.properties 3 Sep 2003 16:04:01 -0000 1.26 @@ -58,6 +58,7 @@ #exclude.block.apples=true #exclude.block.asciiart=true #exclude.block.axis=true +#exclude.block.cron=true #exclude.block.eventcache=true #exclude.block.linotype=true #exclude.block.mail=true 1.77 +20 -1 cocoon-2.1/gump.xml Index: gump.xml =================================================================== RCS file: /home/cvs/cocoon-2.1/gump.xml,v retrieving revision 1.76 retrieving revision 1.77 diff -u -d -b -u -r1.76 -r1.77 --- gump.xml 25 Aug 2003 07:41:18 -0000 1.76 +++ gump.xml 3 Sep 2003 16:04:01 -0000 1.77 @@ -996,6 +996,25 @@ + + + org.apache.cocoon + + + + + + + + + + + + + + + + ${context-root}/WEB-INF/logs/cron.log %7.7{priority} %{time} [%{category}] %{thread}/%{class:short}: %{message}\n%{throwable} true 1.1 cocoon-2.1/src/blocks/cron/conf/cron.xconf Index: cron.xconf =================================================================== false -1 -1 1 60000 RUN true 5000 I'm here 23000 1.1 cocoon-2.1/src/blocks/cron/conf/cron.xsamples Index: cron.xsamples =================================================================== Cron block samples. 1.1 cocoon-2.1/src/blocks/cron/java/org/apache/cocoon/components/cron/ConfigurableCronJob.java Index: ConfigurableCronJob.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ package org.apache.cocoon.components.cron; import java.util.Map; import org.apache.avalon.framework.parameters.Parameters; /** * This is a configurable cron job. Before the execute/run method is called the setup method is invoked. * * @author Giacomo Pati * @version CVS $Id: ConfigurableCronJob.java,v 1.1 2003/09/03 16:04:02 giacomo Exp $ * * @since 2.1.1 */ public interface ConfigurableCronJob extends CronJob { /** * Setup CronJob with additional information first * * @param pars Any Parameters * @param objects Some additional Objects */ void setup(Parameters pars, Map objects); } 1.1 cocoon-2.1/src/blocks/cron/java/org/apache/cocoon/components/cron/CronJob.java Index: CronJob.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ package org.apache.cocoon.components.cron; /** * This is the interface a class has to implement to enable it to be scheduled by a JobScheduler * * @author Giacomo Pati * @version CVS $Id: CronJob.java,v 1.1 2003/09/03 16:04:02 giacomo Exp $ */ public interface CronJob { //~ Instance fields ------------------------------------------------------------------------------------------------ /** The component role */ String ROLE = CronJob.class.getName(); //~ Methods -------------------------------------------------------------------------------------------------------- /** * This methods get called to allow an implementing class to do its supposed job * * @param jobname the name given to this job */ void execute(String jobname); } 1.1 cocoon-2.1/src/blocks/cron/java/org/apache/cocoon/components/cron/JobScheduler.java Index: JobScheduler.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ package org.apache.cocoon.components.cron; import java.util.Date; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.apache.avalon.framework.CascadingException; import org.apache.avalon.framework.parameters.Parameters; /** * This component schedules jobs. * * @author Giacomo Pati * @version CVS $Id: JobScheduler.java,v 1.1 2003/09/03 16:04:02 giacomo Exp $ * * @since 2.1.1 */ public interface JobScheduler { /** The role of a JobScheduler */ String ROLE = JobScheduler.class.getName(); /** * Schedule a time based job. Note that if a CronJob already has same name then it is overwritten. * * @param name the name of the job * @param jobrole The Avalon components role name of the job itself * @param cronSpec the time specification using a cron expression * @param canRunConcurrently whether this job can run even previous scheduled runs are still running */ void addJob(String name, String jobrole, String cronSpec, boolean canRunConcurrently) throws CascadingException; /** * Schedule a time based job. Note that if a CronJob already has same name then it is overwritten. * * @param name the name of the job * @param jobrole The Avalon components role name of the job itself * @param cronSpec the time specification using a cron expression * @param canRunConcurrently whether this job can run even previous scheduled runs are still running * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob */ void addJob(String name, String jobrole, String cronSpec, boolean canRunConcurrently, Parameters params, Map objects) throws CascadingException; /** * Schedule a job. Note that if a CronJob already has the same name then it is overwritten. * * @param name the name of the job * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation * specific class (i.e. org.quartz.Job) * @param cronSpec the time specification using a cron expression * @param canRunConcurrently whether this job can run even previous scheduled runs are still running */ void addJob(String name, Object job, String cronSpec, boolean canRunConcurrently) throws CascadingException; /** * Schedule a job. Note that if a CronJob already has the same name then it is overwritten. * * @param name the name of the job * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation * specific class (i.e. org.quartz.Job) * @param cronSpec the time specification using a cron expression * @param canRunConcurrently whether this job can run even previous scheduled runs are still running * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob */ void addJob(String name, Object job, String cronSpec, boolean canRunConcurrently, Parameters params, Map objects) throws CascadingException; /** * Fire a target once immediately * * @param jobrole The Avalon components role name of the job itself * * @return state of execution successfullness */ boolean fireJob(String jobrole); /** * Fire a target once immediately * * @param jobrole The Avalon components role name of the job itself * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob * * @return state of execution successfullness */ boolean fireJob(String jobrole, Parameters params, Map objects) throws CascadingException; /** * Fire a CronJob once immediately * * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation * specific class (i.e. org.quartz.Job) * * @return state of execution successfullness */ boolean fireJob(Object job); /** * Fire a target once immediately * * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation * specific class (i.e. org.quartz.Job) * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob * * @return state of execution successfullness */ boolean fireJob(Object job, Parameters params, Map objects) throws CascadingException; /** * Fire a target once at a specific date * * @param date The date this job should be scheduled * @param name the name of the job * @param jobrole The Avalon components role name of the job itself */ void fireJobAt(Date date, String name, String jobrole) throws CascadingException; /** * Fire a target once immediately * * @param date The date this job should be scheduled * @param name the name of the job * @param jobrole The Avalon components role name of the job itself * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob */ void fireJobAt(Date date, String name, String jobrole, Parameters params, Map objects) throws CascadingException; /** * Fire a CronJob once immediately * * @param date The date this job should be scheduled * @param name the name of the job * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation * specific class (i.e. org.quartz.Job) */ void fireJobAt(Date date, String name, Object job) throws CascadingException; /** * Fire a target once immediately * * @param date The date this job should be scheduled * @param name the name of the job * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation * specific class (i.e. org.quartz.Job) * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob */ void fireJobAt(Date date, String name, Object job, Parameters params, Map objects) throws CascadingException; /** * Remove a scheduled job by name. * * @param name the name of the job */ void removeJob(String name) throws NoSuchElementException; } 1.1 cocoon-2.1/src/blocks/cron/java/org/apache/cocoon/components/cron/QuartzJobExecutor.java Index: QuartzJobExecutor.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ package org.apache.cocoon.components.cron; import java.util.Map; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.service.ServiceManager; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * This component is resposible to launch a {@link CronJob}s in a Quart Scheduler. * * @author Giacomo Pati * @version CVS $Id: QuartzJobExecutor.java,v 1.1 2003/09/03 16:04:02 giacomo Exp $ */ public class QuartzJobExecutor implements Job { /** Map key for the run status */ private static final String DATA_MAP_KEY_ISRUNNING = "QuartzJobExecutor.isRunning"; /* (non-Javadoc) * @see org.quartz.Job#execute(org.quartz.JobExecutionContext) */ public void execute(final JobExecutionContext context) throws JobExecutionException { final JobDataMap data = context.getJobDetail().getJobDataMap(); final Logger logger = (Logger)data.get(QuartzJobScheduler.DATA_MAP_LOGGER); final String name = (String)data.get(QuartzJobScheduler.DATA_MAP_NAME); final Boolean canRunConcurrentlyB = ((Boolean)data.get(QuartzJobScheduler.DATA_MAP_RUN_CONCURRENT)); final boolean canRunConcurrently = (canRunConcurrentlyB == null ? true : canRunConcurrentlyB.booleanValue()); if ( !canRunConcurrently) { Boolean isRunning = (Boolean)data.get(DATA_MAP_KEY_ISRUNNING); if ((null != isRunning) && isRunning.booleanValue()) { logger.warn("Cron job name '" + name + " already running but configured to not allow concurrent runs. Will discard this scheduled run"); return; } } if (logger.isInfoEnabled()) { logger.info("Scheduling cron job named '" + name + "'"); } Object job = null; String jobrole = null; ServiceManager manager = null; try { jobrole = (String)data.get(QuartzJobScheduler.DATA_MAP_ROLE); if (null == jobrole) { job = data.get(QuartzJobScheduler.DATA_MAP_OBJECT); } else { manager = (ServiceManager)data.get(QuartzJobScheduler.DATA_MAP_MANAGER); job = manager.lookup(jobrole); } if (job instanceof ConfigurableCronJob) { final Parameters params = (Parameters)data.get(QuartzJobScheduler.DATA_MAP_PARAMETERS); final Map objects = (Map)data.get(QuartzJobScheduler.DATA_MAP_OBJECTMAP); ((ConfigurableCronJob)job).setup(params, objects); } data.put(DATA_MAP_KEY_ISRUNNING, new Boolean(true)); if (job instanceof Job) { ((Job)job).execute(context); } else if (job instanceof CronJob) { ((CronJob)job).execute(name); } else if (job instanceof Runnable) { ((Runnable)job).run(); } else { logger.error("job named '" + name + "' is of invalid class: " + job.getClass().getName()); } } catch (final Throwable t) { logger.error("Cron job name '" + name + " died.", t); if (t instanceof JobExecutionException) { throw (JobExecutionException)t; } } finally { data.put(DATA_MAP_KEY_ISRUNNING, new Boolean(false)); if (null != manager) { manager.release(job); } } } } 1.1 cocoon-2.1/src/blocks/cron/java/org/apache/cocoon/components/cron/QuartzJobScheduler.java Index: QuartzJobScheduler.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ /* * Created on Sep 1, 2003 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.apache.cocoon.components.cron; import java.text.ParseException; import java.util.Date; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.apache.avalon.framework.CascadingException; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Startable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.thread.ThreadSafe; import org.quartz.CronTrigger; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.impl.DirectSchedulerFactory; import org.quartz.simpl.RAMJobStore; import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer; import EDU.oswego.cs.dl.util.concurrent.LinkedQueue; import EDU.oswego.cs.dl.util.concurrent.PooledExecutor; /** * This component can either schedule jobs or directly execute one. * * @author giacomo To change the template for this generated type comment go to Window>Preferences>Java>Code * Generation>Code and Comments */ public class QuartzJobScheduler extends AbstractLogEnabled implements JobScheduler, Component, ThreadSafe, Serviceable, Configurable, Startable, Disposable { /** ThreadPool policy RUN */ private static final String POLICY_RUN = "RUN"; /** ThreadPool policy WAIT */ private static final String POLICY_WAIT = "WAIT"; /** ThreadPool policy ABORT */ private static final String POLICY_ABORT = "ABORT"; /** ThreadPool policy DISCARD */ private static final String POLICY_DISCARD = "DISCARD"; /** ThreadPool policy DISCARD-OLDEST */ private static final String POLICY_DISCARD_OLDEST = "DISCARDOLDEST"; /** Map key for the component role */ public static final String DATA_MAP_ROLE = "QuartzJobScheduler.ROLE"; /** Map key for the job object */ public static final String DATA_MAP_OBJECT = "QuartzJobScheduler.Object"; /** Map key for the job name */ public static final String DATA_MAP_NAME = "QuartzJobScheduler.JobName"; /** Map key for the service manager */ public static final String DATA_MAP_MANAGER = "QuartzJobScheduler.ServiceManager"; /** Map key for the logger */ public static final String DATA_MAP_LOGGER = "QuartzJobScheduler.Logger"; /** Map key for the concurrent run property */ public static final String DATA_MAP_RUN_CONCURRENT = "QuartzJobScheduler.RunConcurrently"; /** Map key for additional Parameters */ public static final String DATA_MAP_PARAMETERS = "QuartzJobScheduler.Parameters"; /** Map key for additional Object Map */ public static final String DATA_MAP_OBJECTMAP = "QuartzJobScheduler.Map"; /** The group name */ private static final String DEFAULT_QUARTZ_JOB_GROUP = "Cocoon"; /** The PooledExecutor instance */ private PooledExecutor m_executor; /** The quartz scheduler */ private Scheduler m_scheduler; /** The ServiceManager instance */ private ServiceManager m_manager; /** Should we wait for running jobs to terminate on shutdown ? */ private boolean m_shutdownGraceful; /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.Object, java.lang.String, boolean, org.apache.avalon.framework.parameters.Parameters, java.util.Map) */ public void addJob(final String name, final Object job, final String cronSpec, final boolean canRunConcurrently, final Parameters params, final Map objects) throws CascadingException { final JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(DATA_MAP_OBJECT, job); addJob(name, jobDataMap, cronSpec, canRunConcurrently, params, objects); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.String, java.lang.String, boolean, org.apache.avalon.framework.parameters.Parameters, java.util.Map) */ public void addJob(final String name, final String jobrole, final String cronSpec, final boolean canRunConcurrently, final Parameters params, final Map objects) throws CascadingException { final JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(DATA_MAP_ROLE, jobrole); addJob(name, jobDataMap, cronSpec, canRunConcurrently, params, objects); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.Object, java.lang.String, boolean) */ public void addJob(final String name, final Object job, final String cronSpec, final boolean canRunConcurrently) throws CascadingException { if (!(job instanceof CronJob) && !(job instanceof Runnable) && !(job instanceof Job)) { throw new CascadingException("Job object is neither an instance of " + CronJob.class.getName() + "," + Runnable.class.getName() + " nor " + Job.class.getName()); } addJob(name, job, cronSpec, canRunConcurrently, null, null); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.String, java.lang.String, boolean) */ public void addJob(final String name, final String jobrole, final String cronSpec, final boolean canRunConcurrently) throws CascadingException { addJob(name, jobrole, cronSpec, canRunConcurrently, null, null); } /* (non-Javadoc) * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration) */ public void configure(final Configuration config) throws ConfigurationException { final ThreadPool pool = createThreadPool(config.getChild("thread-pool")); try { DirectSchedulerFactory.getInstance().createScheduler(pool, new RAMJobStore()); m_scheduler = DirectSchedulerFactory.getInstance().getScheduler(); } catch (final SchedulerException se) { throw new ConfigurationException("cannot create a quartz scheduler", se); } final Configuration[] triggers = config.getChild("triggers").getChildren("trigger"); createTriggers(triggers); if (getLogger().isDebugEnabled() && (triggers.length == 0)) { getLogger().debug("no triggers configured at startup"); } } /* (non-Javadoc) * @see org.apache.avalon.framework.activity.Disposable#dispose() */ public void dispose() { try { if (getLogger().isInfoEnabled()) { getLogger().info("shutting down scheduler " + (m_shutdownGraceful ? "graceful (waiting for running jobs to complete)" : "immediately (killing running jobs)")); } m_scheduler.shutdown(m_shutdownGraceful); } catch (final SchedulerException se) { getLogger().error("failure during scheduler shutdown", se); } } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireTarget(java.lang.Object) */ public boolean fireJob(final Object job) { return fireJob(job.getClass().getName(), job); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireTarget(java.lang.String) */ public boolean fireJob(final String jobrole) { try { final Object job = m_manager.lookup(jobrole); return fireJob(jobrole, job); } catch (final ServiceException se) { getLogger().error("cannot fire job " + jobrole, se); } return false; } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireJob(java.lang.Object, org.apache.avalon.framework.parameters.Parameters, java.util.Map) */ public boolean fireJob(final Object job, final Parameters params, final Map objects) throws CascadingException { if (job instanceof ConfigurableCronJob) { ((ConfigurableCronJob)job).setup(params, objects); } return fireJob(job); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireJob(java.lang.String, org.apache.avalon.framework.parameters.Parameters, java.util.Map) */ public boolean fireJob(final String jobrole, final Parameters params, final Map objects) throws CascadingException { try { final Object job = m_manager.lookup(jobrole); if (job instanceof ConfigurableCronJob) { ((ConfigurableCronJob)job).setup(params, objects); } return fireJob(jobrole, job); } catch (final ServiceException se) { getLogger().error("cannot fire job " + jobrole, se); } return false; } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.Object) */ public void fireJobAt(final Date date, final String name, final Object job) throws CascadingException { fireJobAt(date, name, job, null, null); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.String) */ public void fireJobAt(final Date date, final String name, final String jobrole) throws CascadingException { fireJobAt(date, name, jobrole, null, null); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.Object, org.apache.avalon.framework.parameters.Parameters, java.util.Map) */ public void fireJobAt(final Date date, final String name, final Object job, final Parameters params, final Map objects) throws CascadingException { final JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(DATA_MAP_OBJECT, job); addJob(name, jobDataMap, date, true, params, objects); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.String, org.apache.avalon.framework.parameters.Parameters, java.util.Map) */ public void fireJobAt(final Date date, final String name, final String jobrole, final Parameters params, final Map objects) throws CascadingException { final JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(DATA_MAP_ROLE, jobrole); addJob(name, jobDataMap, date, true, params, objects); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#removeJob(java.lang.String) */ public void removeJob(final String name) throws NoSuchElementException { try { m_scheduler.deleteJob(name, DEFAULT_QUARTZ_JOB_GROUP); } catch (final SchedulerException se) { throw new NoSuchElementException(se.getMessage()); } } /* (non-Javadoc) * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) */ public void service(final ServiceManager manager) throws ServiceException { m_manager = manager; } /* (non-Javadoc) * @see org.apache.avalon.framework.activity.Startable#start() */ public void start() throws Exception { m_scheduler.start(); } /* (non-Javadoc) * @see org.apache.avalon.framework.activity.Startable#stop() */ public void stop() throws Exception { m_scheduler.pause(); } /** * Add a job to the scheduler * * @param name The name of the job to add * @param jobDataMap The JobDataMap to use for this job * @param date the date to schedule this job * @param canRunConcurrently whether this job can be run concurrently * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob * * @throws CascadingException thrown in case of errors */ private void addJob(final String name, final JobDataMap jobDataMap, final Date date, final boolean canRunConcurrently, final Parameters params, final Map objects) throws CascadingException { final SimpleTrigger trigger = new SimpleTrigger(name, DEFAULT_QUARTZ_JOB_GROUP, date); addJob(name, jobDataMap, trigger, canRunConcurrently, params, objects); } /** * Add a job to the scheduler * * @param name The name of the job to add * @param jobDataMap The JobDataMap to use for this job * @param cronSpec a Cron time expression * @param canRunConcurrently whether this job can be run concurrently * @param params Additional Parameters to setup CronJob * @param objects A Map with additional object to setup CronJob * * @throws CascadingException thrown in case of errors */ private void addJob(final String name, final JobDataMap jobDataMap, final String cronSpec, final boolean canRunConcurrently, final Parameters params, final Map objects) throws CascadingException { final CronTrigger cronJobEntry = new CronTrigger(name, DEFAULT_QUARTZ_JOB_GROUP); try { cronJobEntry.setCronExpression(cronSpec); } catch (final ParseException pe) { throw new CascadingException(pe.getMessage(), pe); } addJob(name, jobDataMap, cronJobEntry, canRunConcurrently, params, objects); } /** * Add a job to the scheduler * * @param name The name of the job to add * @param jobDataMap The JobDataMap to use for this job * @param trigger a Trigger * @param canRunConcurrently whether this job can be run concurrently * @param params Additional Parameters to setup CronJob (might be null) * @param objects A Map with additional object to setup CronJob (might be null) * * @throws CascadingException thrown in case of errors */ private void addJob(final String name, final JobDataMap jobDataMap, final Trigger trigger, final boolean canRunConcurrently, final Parameters params, final Map objects) throws CascadingException { jobDataMap.put(DATA_MAP_NAME, name); jobDataMap.put(DATA_MAP_LOGGER, getLogger()); jobDataMap.put(DATA_MAP_MANAGER, m_manager); jobDataMap.put(DATA_MAP_RUN_CONCURRENT, new Boolean(canRunConcurrently)); if (null != params) { jobDataMap.put(DATA_MAP_PARAMETERS, params); } if (null != objects) { jobDataMap.put(DATA_MAP_OBJECTMAP, objects); } final JobDetail detail = new JobDetail(name, DEFAULT_QUARTZ_JOB_GROUP, QuartzJobExecutor.class); detail.setJobDataMap(jobDataMap); if (getLogger().isInfoEnabled()) { getLogger().info("Adding CronJob '" + trigger.getFullName() + "'"); if (getLogger().isDebugEnabled()) { if (trigger instanceof CronTrigger) { getLogger().debug("Time schedule summary:\n" + ((CronTrigger)trigger).getExpressionSummary()); } else if (trigger instanceof SimpleTrigger) { getLogger().debug("Next scheduled time: " + ((SimpleTrigger)trigger).getNextFireTime()); } } } try { m_scheduler.scheduleJob(detail, trigger); } catch (final SchedulerException se) { throw new CascadingException(se.getMessage(), se); } } /** * Create a ThreadPool * * @param poolConfig Configuration element for the thread pool * * @return ThreadPool */ private ThreadPool createThreadPool(final Configuration poolConfig) { final boolean useQueueing = poolConfig.getChild("use-queueing").getValueAsBoolean(false); final int queueSize = poolConfig.getChild("queue-size").getValueAsInteger(-1); if (useQueueing) { if (queueSize > 0) { m_executor = new PooledExecutor(new BoundedBuffer(queueSize)); } else { m_executor = new PooledExecutor(new LinkedQueue()); } } else { m_executor = new PooledExecutor(); } final int maxPoolSize = poolConfig.getChild("max-pool-size").getValueAsInteger(-1); if (maxPoolSize > 0) { m_executor.setMaximumPoolSize(maxPoolSize); } else { m_executor.setMaximumPoolSize(PooledExecutor.DEFAULT_MAXIMUMPOOLSIZE); } final int minPoolSize = poolConfig.getChild("min-pool-size").getValueAsInteger(-1); if (minPoolSize > 0) { m_executor.setMinimumPoolSize(minPoolSize); } else { m_executor.setMinimumPoolSize(PooledExecutor.DEFAULT_MINIMUMPOOLSIZE); } final int keepAliveTimeMs = poolConfig.getChild("keep-alive-time-ms").getValueAsInteger(-1); if (keepAliveTimeMs > 0) { m_executor.setKeepAliveTime(keepAliveTimeMs); } else { m_executor.setKeepAliveTime(PooledExecutor.DEFAULT_KEEPALIVETIME); } final String blockPolicy = poolConfig.getChild("block-policy").getValue(null); if (blockPolicy != null) { if (blockPolicy.equalsIgnoreCase(POLICY_ABORT)) { m_executor.abortWhenBlocked(); } else if (blockPolicy.equalsIgnoreCase(POLICY_DISCARD)) { m_executor.discardWhenBlocked(); } else if (blockPolicy.equalsIgnoreCase(POLICY_DISCARD_OLDEST)) { m_executor.discardOldestWhenBlocked(); } else if (blockPolicy.equalsIgnoreCase(POLICY_RUN)) { m_executor.runWhenBlocked(); } else if (blockPolicy.equalsIgnoreCase(POLICY_WAIT)) { m_executor.waitWhenBlocked(); } else { getLogger().warn("Unknown block-policy configuration '" + blockPolicy + "'. Should be one of '" + POLICY_ABORT + "','" + POLICY_DISCARD + "','" + POLICY_DISCARD_OLDEST + "','" + POLICY_RUN + "','" + POLICY_WAIT + "'. Will use '" + POLICY_RUN + "'"); } } m_shutdownGraceful = poolConfig.getChild("shutdown-graceful").getValueAsBoolean(true); final int shutdownWaitTimeMs = poolConfig.getChild("shutdown-wait-time-ms").getValueAsInteger(-1); final ThreadPool pool = new ThreadPool(m_executor, shutdownWaitTimeMs); pool.enableLogging(getLogger()); if (getLogger().isInfoEnabled()) { getLogger().info("using a PooledExecutor as ThreadPool with queueing=" + useQueueing + (useQueueing ? (",queue-size=" + ((queueSize > 0) ? ("" + queueSize) : "default")) : "") + ",max-pool-size=" + m_executor.getMaximumPoolSize() + ",min-pool-size=" + m_executor.getMinimumPoolSize() + ",keep-alive-time-ms=" + m_executor.getKeepAliveTime() + ",block-policy='" + blockPolicy + "',shutdown-wait-time-ms=" + ((shutdownWaitTimeMs > 0) ? ("" + shutdownWaitTimeMs) : "default")); } return pool; } /** * Create the tiggers * * @param tiggers array of tigger configuration elements * * @throws ConfigurationException thrown in case of configuration failures */ private void createTriggers(final Configuration[] tiggers) throws ConfigurationException { for (int i = 0; i < tiggers.length; i++) { String cron = tiggers[i].getChild("cron").getValue(null); if (null == cron) { final String seconds = tiggers[i].getChild("seconds").getValue("0"); final String minutes = tiggers[i].getChild("minutes").getValue("*"); final String hours = tiggers[i].getChild("hours").getValue("*"); final String days = tiggers[i].getChild("days").getValue("*"); final String months = tiggers[i].getChild("months").getValue("*"); final String weekdays = tiggers[i].getChild("weekdays").getValue("?"); final String years = tiggers[i].getChild("years").getValue("*"); cron = seconds + " " + minutes + " " + hours + " " + days + " " + months + " " + weekdays + " " + years; } try { addJob(tiggers[i].getAttribute("name"), tiggers[i].getAttribute("target"), cron, tiggers[i].getAttributeAsBoolean("concurrent-runs", true)); } catch (final CascadingException ce) { throw new ConfigurationException("failed adding trigger to scheduler", ce); } } } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.JobScheduler#fireTarget(java.lang.Object) */ private boolean fireJob(final String name, final Object job) { try { if (job instanceof CronJob) { m_executor.execute(new Runnable() { public void run() { ((CronJob)job).execute(name); } }); } else if (job instanceof Runnable) { m_executor.execute((Runnable)job); } else { getLogger().error("job named '" + name + "' is of invalid class: " + job.getClass().getName()); return false; } return true; } catch (final InterruptedException ie) { getLogger().error("job " + name + " interrupted", ie); } return false; } /** * A ThreadPool for the Quartz Scheduler based on Doug Leas concurrency utilities PooledExecutor * * @author Giacomo Pati * @version CVS $Id: QuartzJobScheduler.java,v 1.1 2003/09/03 16:04:02 giacomo Exp $ */ private static class ThreadPool extends AbstractLogEnabled implements org.quartz.spi.ThreadPool { /** Our executor thread pool */ private PooledExecutor m_executor; /** How long to wait for running jobs to terminate on disposition */ private int m_shutdownWaitTimeMs; /** * */ public ThreadPool(final PooledExecutor executor, final int shutownWaitTimeMs) { super(); m_executor = executor; m_shutdownWaitTimeMs = shutownWaitTimeMs; } /* (non-Javadoc) * @see org.quartz.spi.ThreadPool#getPoolSize() */ public int getPoolSize() { return m_executor.getMaximumPoolSize(); } /* (non-Javadoc) * @see org.quartz.spi.ThreadPool#initialize() */ public void initialize() { } /* (non-Javadoc) * @see org.quartz.spi.ThreadPool#runInThread(java.lang.Runnable) */ public boolean runInThread(final Runnable job) { try { m_executor.execute(job); } catch (final InterruptedException ie) { getLogger().error("Cronjob failed", ie); } return true; } /* (non-Javadoc) * @see org.quartz.spi.ThreadPool#shutdown(boolean) */ public void shutdown(final boolean waitForJobsToComplete) { if (waitForJobsToComplete) { m_executor.shutdownAfterProcessingCurrentlyQueuedTasks(); } else { m_executor.shutdownNow(); } try { if (m_shutdownWaitTimeMs > 0) { if (!m_executor.awaitTerminationAfterShutdown(m_shutdownWaitTimeMs)) { getLogger().warn("scheduled cron jobs are not terminating withing " + m_shutdownWaitTimeMs + "ms, Will shut them down by interruption"); m_executor.interruptAll(); m_executor.shutdownNow(); } } m_executor.awaitTerminationAfterShutdown(); } catch (final InterruptedException ie) { getLogger().error("cannot shutdown Executor", ie); } } } } 1.1 cocoon-2.1/src/blocks/cron/java/org/apache/cocoon/components/cron/TestCronJob.java Index: TestCronJob.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ package org.apache.cocoon.components.cron; import java.util.Date; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.logger.AbstractLogEnabled; /** * A simple test CronJob. * * @author Giacomo Pati * @version CVS $Id: TestCronJob.java,v 1.1 2003/09/03 16:04:02 giacomo Exp $ * * @since 2.1.1 */ public class TestCronJob extends AbstractLogEnabled implements CronJob, Configurable, Component { //~ Instance fields ------------------------------------------------------------------------------------------------ /** The configured message */ private String m_msg; /** The configured sleep time */ private int m_sleep; //~ Methods -------------------------------------------------------------------------------------------------------- /* (non-Javadoc) * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration) */ public void configure(final Configuration config) throws ConfigurationException { m_msg = config.getChild("msg").getValue("I was not configured"); m_sleep = config.getChild("sleep").getValueAsInteger(11000); } /* (non-Javadoc) * @see org.apache.cocoon.components.cron.CronJob#execute(java.lang.String) */ public void execute(String name) { getLogger().info("CronJob " + name + " launched at " + new Date() + " with message: " + m_msg); try { Thread.sleep(m_sleep); } catch (final InterruptedException ie) { //getLogger().error("CronJob " + name + " interrupted", ie); } getLogger().info("CronJob " + name + " finished at " + new Date() + " with message: " + m_msg); } } 1.1 cocoon-2.1/src/blocks/cron/lib/quartz-1.0.7.jar <> 1.1 cocoon-2.1/src/blocks/cron/samples/cron.xsp Index: cron.xsp ===================================================================
Cron Job Scheduler Sample

Some sample will follow ...

1.1 cocoon-2.1/src/blocks/cron/samples/docs.xml Index: docs.xml ===================================================================
Cron Job Scheduler

This implementation of the Java interface JobScheduler is based on the Quartz job scheduling project and the PooledExecutor of Doug Leas Concurrency Package as a ThreadPool implementation for the Quartz Scheduler.

WARNING: Consider the JobScheduler interface as beta in terms of defined functionality as it will be extended with additional requirements in the near future (i.e. getJobList).

This QuartzJobScheduler implementation is written as a standard Avalon component. So, its definition you'll find in the cocoon.xconf file of Cocoon if you've included the cron-block in your build (see block.properties or local.block.properties file respectively).

The snippet below shows the configuration example of the component itself:

<component role="org.apache.cocoon.components.cron.JobScheduler" class="org.apache.cocoon.components.cron.QuartzJobScheduler" logger="cron"> <thread-pool> ... </thread-pool> <triggers> ... </triggers> </component>

There is nothing special about it. As you could see from the snippet above, inside the job scheduler component definition there are two parts:

  • ThreadPool definition
  • Trigger definitions

ThreadPool

The ThreadPool definition look like this:

<!-- Definitions for a thread pool used to schedule jobs --> <thread-pool> <!-- Should we queue up execution requests if the pool is busy? Defaults to false --> <use-queueing>false</use-queueing> <!-- How big should the queue be. Defaults to unlimited size (<0 == default) --> <queue-size>-1</queue-size> <!-- The maximum size of the pool. Defaults to Integer.MAX_VALUE (<0 == default) --> <max-pool-size>-1</max-pool-size> <!-- The minimum size of the pool.Defaults to 1 (<0 == default) --> <min-pool-size>1</min-pool-size> <!-- How long will an idle thread be kept before it will be discarded. Defaults to 60000ms (<0 == default) --> <keep-alive-time-ms>60000</keep-alive-time-ms> <!-- Which blocking policy should be used if the maximum pool size and queue size is bounded: Run: (default) The thread making the execute request runs the task itself. This policy helps guard against lockup. Wait: Wait until a thread becomes available. Abort: Throw a RuntimeException Discard: Throw away the current request and return. DiscardOldest: Throw away the oldest request and return. --> <block-policy>RUN</block-policy> <!-- Should queued and running jobs be given a chance to finished on system shutdown. Defaults to true --> <shutdown-graceful>true</shutdown-graceful> <!-- The maximum time to wait for running jobs to complete. Defaults to unlimited time (<0 == default) --> <shutdown-wait-time-ms>5000</shutdown-wait-time-ms> </thread-pool>

As mentioned in the beginning, more information about the thread pool details of the base PooledExecutor class can be found there.

Triggers

The trigger definition section consists of a single <triggers> element with as much as needed <trigger> elements inside it. A <trigger> element looks like:

<!-- Definintions of triggers --> <triggers> <!-- A trigger element has the following attributes: name: A name for the trigger. Mandatory target: A role name to lookup the job object in the ServiceManager. Mandatory concurrent-runs: Is it allowed to reschedule a job even if the previous one is still running. Optionl, defaults to true. A trigger element has the following child elements: cron: A string expression defining the scheduling timing. Optional. If not specified the following elements are explored: seconds: A string expression for the secods part of a cron expression. minutes: A string expression for the secods part of a cron expression. hours: A string expression for the secods part of a cron expression. days: A string expression for the secods part of a cron expression. month: A string expression for the secods part of a cron expression. weekdays: A string expression for the secods part of a cron expression. years: A string expression for the secods part of a cron expression. For detailed information about the expressions look at the documentation --> <trigger name="test-job1" target="org.apache.cocoon.components.cron.CronJob/test" concurrent-runs="false"> <cron>*/12 * * * * ? *</cron> </trigger> <trigger name="test-job2" target="org.apache.cocoon.components.cron.CronJob/test" concurrent-runs="true"> <seconds>*/12</seconds> <minutes>*/5</minutes> <hours>8,10,12,14,16,18</hours> <days>?</days> <months>*</months> <weekdays>SUN-FRI</weekdays> </trigger> </triggers>

The <cron> element is simply the concatenation of the values of the elements <seconds>, <minutes>, <hours>, <days>, <months>, <weekdays>, and <year> delimeted with spaces. You can use either form but the <cron> element will be preferred by the implementation if you use both forms together in one <trigger> element. A description of the expressions used inside the <trigger> elements is described in the CronTrigger class.

Job Components

The CronJob object doing your work can be defined in the cocoon.xconf file as a regular Avalon components. The role attribute given to this component is refered to by the target attribute in the <trigger> element above. Below is the sample for the TestCronJob component.

<!-- sample definition of cron job --> <component role="org.apache.cocoon.components.cron.CronJob/test" class="org.apache.cocoon.components.cron.TestCronJob" logger="cron.test"> <msg>I'm here</msg> <sleep>23000</sleep> </component>
1.1 cocoon-2.1/src/blocks/cron/samples/samples.xml Index: samples.xml =================================================================== Documentation for the Cron component. 1.1 cocoon-2.1/src/blocks/cron/samples/sitemap.xmap Index: sitemap.xmap ===================================================================