This is an automated email from the ASF dual-hosted git repository. martin_s pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/archiva-redback-components-spring-quartz.git
commit 1d044533376007470f0688bed71d767452fceafd Author: Olivier Lamy <ol...@apache.org> AuthorDate: Fri Apr 6 09:33:40 2012 +0000 import redback components sources http://svn.codehaus.org/redback/components/trunk/ r1724. git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-components/trunk@1310262 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 91 +++++ .../redback/components/scheduler/AbstractJob.java | 96 +++++ .../scheduler/CronExpressionValidator.java | 441 +++++++++++++++++++++ .../components/scheduler/DefaultJobListener.java | 125 ++++++ .../components/scheduler/DefaultScheduler.java | 180 +++++++++ .../redback/components/scheduler/Scheduler.java | 60 +++ .../configuration/SchedulerConfiguration.java | 133 +++++++ src/main/resources/META-INF/spring-context.xml | 34 ++ .../scheduler/CronExpressionValidatorTest.java | 127 ++++++ .../redback/components/scheduler/JobOne.java | 79 ++++ .../components/scheduler/SchedulerTest.java | 102 +++++ src/test/resources/spring-context.xml | 41 ++ 12 files changed, 1509 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5afe0b9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.codehaus.redback.components</groupId> + <artifactId>redback-components</artifactId> + <version>1.3-SNAPSHOT</version> + <relativePath>../redback-components-parent/pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>spring-quartz</artifactId> + <name>Spring Quartz Component</name> + <version>1.1-SNAPSHOT</version> + + <url>http://redback.codehaus.org/components/${project.artifactId}</url> + + <distributionManagement> + <site> + <id>codehaus.org</id> + <url>dav:https://dav.codehaus.org/redback/components/${project.artifactId}</url> + </site> + </distributionManagement> + + <scm> + <connection>scm:svn:https://svn.codehaus.org/redback/components/trunk/spring-quartz</connection> + <developerConnection>scm:svn:https://svn.codehaus.org/redback/components/trunk/spring-quartz</developerConnection> + <url>http://fisheye.codehaus.org/browse/redback/components/trunk/spring-quartz</url> + </scm> + + <dependencies> + <dependency> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + </dependency> + <dependency> + <groupId>javax.annotation</groupId> + <artifactId>jsr250-api</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + <dependency> + <groupId>org.quartz-scheduler</groupId> + <artifactId>quartz</artifactId> + <version>2.1.1</version> + <exclusions> + <exclusion> + <groupId>c3p0</groupId> + <artifactId>c3p0</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <forkedProcessTimeoutInSeconds>60</forkedProcessTimeoutInSeconds> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/src/main/java/org/codehaus/redback/components/scheduler/AbstractJob.java b/src/main/java/org/codehaus/redback/components/scheduler/AbstractJob.java new file mode 100644 index 0000000..2956c74 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/scheduler/AbstractJob.java @@ -0,0 +1,96 @@ +package org.codehaus.redback.components.scheduler; + +/* + * 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. + */ + +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.InterruptableJob; +import org.quartz.UnableToInterruptJobException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class from which all <code>Job</code>s running in the + * scheduler should be derived from if they want access to the + * ServiceBroker. + * + * @author <a href="mailto:ja...@zenplex.com">Jason van Zyl</a> + * @version $Id$ + */ +public abstract class AbstractJob + implements InterruptableJob +{ + + private Logger log = LoggerFactory.getLogger( getClass() ); + + /** JobDataMap tag for the job's logger. */ + public static final String LOGGER = "JOB_LOGGER"; + + /** JobDataMap tag for the job's context. */ + public static final String CONTEXT = "JOB_CONTEXT"; + + /** JobDataMap tag for the job's service broker. */ + public static final String SERVICE_MANAGER = "JOB_SERVICE_MANAGER"; + + /** JobDataMap tag for the job's configuration. */ + public static final String EXECUTION_CONFIGURATION = "JOB_EXECUTION_CONFIGURATION"; + + /** Job Data Map */ + private JobDataMap jobDataMap; + + private boolean interrupted; + + /** Set Job Data Map */ + public void setJobDataMap(JobDataMap jobDataMap) + { + this.jobDataMap = jobDataMap; + } + + /** Get Job Data Map */ + public JobDataMap getJobDataMap() + { + return jobDataMap; + } + + /** Get the Logger. */ + public Logger getLogger() + { + return (Logger) getJobDataMap().get(LOGGER); + } + + + + /** Execute the Job. */ + public abstract void execute(JobExecutionContext context) + throws JobExecutionException; + + public boolean isInterrupted() + { + return interrupted; + } + + public void interrupt() + throws UnableToInterruptJobException + { + interrupted = true; + } +} diff --git a/src/main/java/org/codehaus/redback/components/scheduler/CronExpressionValidator.java b/src/main/java/org/codehaus/redback/components/scheduler/CronExpressionValidator.java new file mode 100644 index 0000000..a6fe180 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/scheduler/CronExpressionValidator.java @@ -0,0 +1,441 @@ +package org.codehaus.redback.components.scheduler; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * 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. + */ + +import org.apache.commons.lang.StringUtils; +import org.quartz.CronTrigger; +import org.quartz.impl.triggers.CronTriggerImpl; +import org.springframework.stereotype.Service; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; + +/** + * @author <a href="mailto:eveni...@codehaus.org">Emmanuel Venisse</a> + * @version $Id$ + */ +@Service +public final class CronExpressionValidator +{ + + /** + * Validates a cron expression. + * + * @param cronExpression The expression to validate + * @return True is expression is valid + */ + public boolean validate( String cronExpression ) + { + try + { + String[] cronParams = StringUtils.split( cronExpression ); + + if ( cronParams.length < 6 || cronParams.length > 7 ) + { + return false; + } + + CronTriggerImpl cronTrigger = new CronTriggerImpl(); + + cronTrigger.setCronExpression( cronExpression ); + + if ( cronParams[3].equals( "?" ) || cronParams[5].equals( "?" ) ) + { + //Check seconds param + if ( !checkSecondsField( cronParams[0] ) ) + { + return false; + } + + //Check minutes param + if ( !checkMinutesField( cronParams[1] ) ) + { + return false; + } + + //Check hours param + if ( !checkHoursField( cronParams[2] ) ) + { + return false; + } + + //Check day-of-month param + if ( !checkDayOfMonthField( cronParams[3] ) ) + { + return false; + } + + //Check months param + if ( !checkMonthsField( cronParams[4] ) ) + { + return false; + } + + //Check day-of-week param + if ( !checkDayOfWeekField( cronParams[5] ) ) + { + return false; + } + + //Check year param + if ( cronParams.length == 7 ) + { + if ( !checkYearField( cronParams[6] ) ) + { + return false; + } + } + + return true; + } + else + { + return false; + } + } + catch ( ParseException e ) + { + return false; + } + } + + private boolean checkSecondsField( String secondsField ) + { + return checkField( secondsField, 0, 59 ); + } + + private boolean checkMinutesField( String minutesField ) + { + return checkField( minutesField, 0, 59 ); + } + + private boolean checkHoursField( String hoursField ) + { + return checkField( hoursField, 0, 23 ); + } + + private boolean checkDayOfMonthField( String dayOfMonthField ) + { + if ( "?".equals( dayOfMonthField ) ) + { + return true; + } + + if ( dayOfMonthField.indexOf( "L" ) >= 0 ) + { + return checkFieldWithLetter( dayOfMonthField, "L", 1, 7, -1, -1 ); + } + else if ( dayOfMonthField.indexOf( "W" ) >= 0 ) + { + return checkFieldWithLetter( dayOfMonthField, "W", 1, 31, -1, -1 ); + } + else if ( dayOfMonthField.indexOf( "C" ) >= 0 ) + { + return checkFieldWithLetter( dayOfMonthField, "C", 1, 31, -1, -1 ); + } + else + { + return checkField( dayOfMonthField, 1, 31 ); + } + } + + private boolean checkMonthsField( String monthsField ) + { + monthsField = StringUtils.replace( monthsField, "JAN", "1" ); + monthsField = StringUtils.replace( monthsField, "FEB", "2" ); + monthsField = StringUtils.replace( monthsField, "MAR", "3" ); + monthsField = StringUtils.replace( monthsField, "APR", "4" ); + monthsField = StringUtils.replace( monthsField, "MAY", "5" ); + monthsField = StringUtils.replace( monthsField, "JUN", "6" ); + monthsField = StringUtils.replace( monthsField, "JUL", "7" ); + monthsField = StringUtils.replace( monthsField, "AUG", "8" ); + monthsField = StringUtils.replace( monthsField, "SEP", "9" ); + monthsField = StringUtils.replace( monthsField, "OCT", "10" ); + monthsField = StringUtils.replace( monthsField, "NOV", "11" ); + monthsField = StringUtils.replace( monthsField, "DEC", "12" ); + + return checkField( monthsField, 1, 31 ); + } + + private boolean checkDayOfWeekField( String dayOfWeekField ) + { + dayOfWeekField = StringUtils.replace( dayOfWeekField, "SUN", "1" ); + dayOfWeekField = StringUtils.replace( dayOfWeekField, "MON", "2" ); + dayOfWeekField = StringUtils.replace( dayOfWeekField, "TUE", "3" ); + dayOfWeekField = StringUtils.replace( dayOfWeekField, "WED", "4" ); + dayOfWeekField = StringUtils.replace( dayOfWeekField, "THU", "5" ); + dayOfWeekField = StringUtils.replace( dayOfWeekField, "FRI", "6" ); + dayOfWeekField = StringUtils.replace( dayOfWeekField, "SAT", "7" ); + + if ( "?".equals( dayOfWeekField ) ) + { + return true; + } + + if ( dayOfWeekField.indexOf( "L" ) >= 0 ) + { + return checkFieldWithLetter( dayOfWeekField, "L", 1, 7, -1, -1 ); + } + else if ( dayOfWeekField.indexOf( "C" ) >= 0 ) + { + return checkFieldWithLetter( dayOfWeekField, "C", 1, 7, -1, -1 ); + } + else if ( dayOfWeekField.indexOf( "#" ) >= 0 ) + { + return checkFieldWithLetter( dayOfWeekField, "#", 1, 7, 1, 5 ); + } + else + { + return checkField( dayOfWeekField, 1, 7 ); + } + } + + private boolean checkYearField( String yearField ) + { + return checkField( yearField, 1970, 2099 ); + } + + private boolean checkField( String secondsField, int minimal, int maximal ) + { + if ( secondsField.indexOf( "-" ) > -1 ) + { + String startValue = secondsField.substring( 0, secondsField.indexOf( "-" ) ); + String endValue = secondsField.substring( secondsField.indexOf( "-" ) + 1 ); + + if ( !( checkIntValue( startValue, minimal, maximal ) && checkIntValue( endValue, minimal, maximal ) ) ) + { + return false; + } + try + { + int startVal = Integer.parseInt( startValue ); + int endVal = Integer.parseInt( endValue ); + + return endVal > startVal; + + } + catch ( NumberFormatException e ) + { + return false; + } + } + else if ( secondsField.indexOf( "," ) > -1 ) + { + return checkListField( secondsField, minimal, maximal ); + } + else if ( secondsField.indexOf( "/" ) > -1 ) + { + return checkIncrementField( secondsField, minimal, maximal ); + } + else if ( secondsField.indexOf( "*" ) != -1 ) + { + return true; + } + else + { + return checkIntValue( secondsField, minimal, maximal ); + } + } + + private boolean checkFieldWithLetter( String value, String letter, int minimalBefore, int maximalBefore, + int minimalAfter, int maximalAfter ) + { + boolean canBeAlone = false; + boolean canHaveIntBefore = false; + boolean canHaveIntAfter = false; + boolean mustHaveIntBefore = false; + boolean mustHaveIntAfter = false; + + if ( "L".equals( letter ) ) + { + canBeAlone = true; + canHaveIntBefore = true; + canHaveIntAfter = false; + mustHaveIntBefore = false; + mustHaveIntAfter = false; + } + if ( "W".equals( letter ) || "C".equals( letter ) ) + { + canBeAlone = false; + canHaveIntBefore = true; + canHaveIntAfter = false; + mustHaveIntBefore = true; + mustHaveIntAfter = false; + } + if ( "#".equals( letter ) ) + { + canBeAlone = false; + canHaveIntBefore = true; + canHaveIntAfter = true; + mustHaveIntBefore = true; + mustHaveIntAfter = true; + } + + String beforeLetter = ""; + String afterLetter = ""; + + if ( value.indexOf( letter ) >= 0 ) + { + beforeLetter = value.substring( 0, value.indexOf( letter ) ); + } + + if ( !value.endsWith( letter ) ) + { + afterLetter = value.substring( value.indexOf( letter ) + 1 ); + } + + if ( value.indexOf( letter ) >= 0 ) + { + if ( letter.equals( value ) ) + { + return canBeAlone; + } + + if ( canHaveIntBefore ) + { + if ( mustHaveIntBefore && beforeLetter.length() == 0 ) + { + return false; + } + + if ( !checkIntValue( beforeLetter, minimalBefore, maximalBefore, true ) ) + { + return false; + } + } + else + { + if ( beforeLetter.length() > 0 ) + { + return false; + } + } + + if ( canHaveIntAfter ) + { + if ( mustHaveIntAfter && afterLetter.length() == 0 ) + { + return false; + } + + if ( !checkIntValue( afterLetter, minimalAfter, maximalAfter, true ) ) + { + return false; + } + } + else + { + if ( afterLetter.length() > 0 ) + { + return false; + } + } + } + + return true; + } + + private boolean checkIncrementField( String value, int minimal, int maximal ) + { + String start = value.substring( 0, value.indexOf( "/" ) ); + + String increment = value.substring( value.indexOf( "/" ) + 1 ); + + if ( !"*".equals( start ) ) + { + return checkIntValue( start, minimal, maximal ) && checkIntValue( increment, minimal, maximal, false ); + } + else + { + return checkIntValue( increment, minimal, maximal ); + } + } + + private boolean checkListField( String value, int minimal, int maximal ) + { + StringTokenizer st = new StringTokenizer( value, "," ); + + List values = new ArrayList(); + + while ( st.hasMoreTokens() ) + { + values.add( st.nextToken() ); + } + + int previousValue = -1; + + for ( Iterator i = values.iterator(); i.hasNext(); ) + { + String currentValue = (String) i.next(); + + if ( !checkIntValue( currentValue, minimal, maximal ) ) + { + return false; + } + + try + { + int val = Integer.parseInt( currentValue ); + + if ( val <= previousValue ) + { + return false; + } + else + { + previousValue = val; + } + } + catch ( NumberFormatException e ) + { + // we have always an int + } + } + + return true; + } + + private boolean checkIntValue( String value, int minimal, int maximal ) + { + return checkIntValue( value, minimal, maximal, true ); + } + + private static boolean checkIntValue( String value, int minimal, int maximal, boolean checkExtremity ) + { + try + { + int val = Integer.parseInt( value ); + + if ( checkExtremity ) + { + if ( val < minimal || val > maximal ) + { + return false; + } + } + + return true; + } + catch ( NumberFormatException e ) + { + return false; + } + } +} diff --git a/src/main/java/org/codehaus/redback/components/scheduler/DefaultJobListener.java b/src/main/java/org/codehaus/redback/components/scheduler/DefaultJobListener.java new file mode 100644 index 0000000..db12893 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/scheduler/DefaultJobListener.java @@ -0,0 +1,125 @@ +package org.codehaus.redback.components.scheduler; + +/* ---------------------------------------------------------------------------- + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Plexus", 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 apa...@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 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 (INCLUDING, 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. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + * + * ---------------------------------------------------------------------------- + */ + +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.JobListener; + +/** + * Currently the role this class plays is set the value of the <code>JobDataMap</code> + * in the job so that the convenience methods for accessing the logger, context, + * service broker and configuration will work as expected. + * + * @author <a href="mailto:ja...@zenplex.com">Jason van Zyl</a> + * @version $Id$ + */ +public class DefaultJobListener + implements JobListener +{ + /** + * <p> + * <p/> + * Get the name of the <code>JobListener</code>.</p> + */ + public String getName() + { + return "DefaultJobLister"; + } + + /** + * <p> + * <p/> + * Called by the <code>{@link Scheduler}</code> when a <code>{@link Job}</code> + * is about to be executed (an associated <code>{@link org.quartz.Trigger}</code> has + * occured).</p> + */ + public void jobToBeExecuted( JobExecutionContext context ) + { + Job job = context.getJobInstance(); + + // Only attempt to set the ServiceBroker when we are dealing + // with subclasses AbstractJob. + if ( job instanceof AbstractJob ) + { + ( (AbstractJob) job ).setJobDataMap( context.getJobDetail().getJobDataMap() ); + } + } + + public void jobExecutionVetoed( JobExecutionContext jobExecutionContext ) + { + } + + /** + * <p> + * <p/> + * Called by the <code>{@link Scheduler}</code> after a <code>{@link Job}</code> + * has been executed, and be for the associated <code>Trigger</code>'s + * <code>triggered(xx)</code> method has been called.</p> + */ + public void jobWasExecuted( JobExecutionContext context, JobExecutionException jobException ) + { + Job job = context.getJobInstance(); + + // Only attempt to null the ServiceBroker when we are dealing + // with subclasses AbstractJob. + if ( job instanceof AbstractJob ) + { + } + } +} diff --git a/src/main/java/org/codehaus/redback/components/scheduler/DefaultScheduler.java b/src/main/java/org/codehaus/redback/components/scheduler/DefaultScheduler.java new file mode 100644 index 0000000..cec012f --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/scheduler/DefaultScheduler.java @@ -0,0 +1,180 @@ +package org.codehaus.redback.components.scheduler; + +/* + * 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. + */ + +import org.quartz.JobKey; +import org.quartz.JobListener; +import org.quartz.Matcher; +import org.quartz.SchedulerException; +import org.quartz.SchedulerFactory; +import org.quartz.Trigger; +import org.quartz.TriggerListener; +import org.quartz.core.QuartzScheduler; +import org.quartz.impl.JobDetailImpl; +import org.quartz.impl.StdScheduler; +import org.quartz.impl.StdSchedulerFactory; +import org.quartz.utils.Key; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.Properties; + +public class DefaultScheduler + implements Scheduler +{ + + private Logger log = LoggerFactory.getLogger( getClass() ); + + private Properties properties; + + private StdScheduler scheduler; + + public void scheduleJob( JobDetailImpl jobDetail, Trigger trigger ) + throws SchedulerException + { + if ( jobDetail == null || jobDetail.getName() == null ) + { + throw new SchedulerException( "No job or no job name - cannot schedule this job" ); + } + + if ( jobExists( jobDetail.getName(), jobDetail.getGroup() ) ) + { + log.warn( "Will not schedule this job as a job {" + jobDetail.getName() + ":" + jobDetail.getGroup() + + "} already exists." ); + + return; + } + + try + { + scheduler.scheduleJob( jobDetail, trigger ); + } + catch ( SchedulerException e ) + { + throw new SchedulerException( "Error scheduling job.", e ); + } + catch ( Exception e ) + { + throw new SchedulerException( "Error scheduling job (Verify your cron expression).", e ); + } + } + + public void addGlobalJobListener( JobListener listener ) + throws SchedulerException + { + scheduler.getListenerManager().addJobListener( listener, new AllMatch() ); + } + + public void addGlobalTriggerListener( TriggerListener listener ) + throws SchedulerException + { + scheduler.getListenerManager().addTriggerListener( listener, new AllMatch() ); + } + + private static class AllMatch<R extends Key<?>> implements Matcher<R> + { + public boolean isMatch( R key ) + { + return true; + } + } + + @PostConstruct + public void initialize() + throws SchedulerException + { + SchedulerFactory factory = new StdSchedulerFactory( properties ); + + scheduler = (StdScheduler) factory.getScheduler(); + + scheduler.start(); + + } + + @PreDestroy + public void stop() + { + scheduler.shutdown(); + } + + public void unscheduleJob( String jobName, String groupName ) + throws SchedulerException + { + if ( jobName == null ) + { + throw new SchedulerException( "Job name null - cannot unschedule job" ); + } + + try + { + if ( jobExists( jobName, groupName ) ) + { + scheduler.deleteJob( new JobKey( jobName, groupName ) ); + } + } + catch ( SchedulerException e ) + { + throw new SchedulerException( "Error unscheduling job.", e ); + } + } + + public boolean interruptSchedule( String jobName, String groupName ) + throws SchedulerException + { + try + { + return scheduler.interrupt( new JobKey( jobName, groupName ) ); + } + catch ( Exception e ) + { + throw new SchedulerException( "Can't interrup job \"" + jobName + "\".", e ); + } + } + + private boolean jobExists( String jobName, String jobGroup ) + throws SchedulerException + { + + return ( scheduler.getJobDetail( new JobKey( jobName, jobGroup ) ) != null ); + } + + public void shutdown( boolean waitForJobsToComplete ) + { + log.info( "call shutdown waitForJobsToComplete : {}", waitForJobsToComplete ); + scheduler.shutdown( waitForJobsToComplete ); + } + + public StdScheduler getScheduler() + { + return scheduler; + } + + public void setProperties( Properties properties ) + { + this.properties = properties; + } + + public Properties getProperties() + { + return properties; + } +} diff --git a/src/main/java/org/codehaus/redback/components/scheduler/Scheduler.java b/src/main/java/org/codehaus/redback/components/scheduler/Scheduler.java new file mode 100644 index 0000000..39f1100 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/scheduler/Scheduler.java @@ -0,0 +1,60 @@ +package org.codehaus.redback.components.scheduler; + +/* + * 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. + */ + +import org.quartz.JobListener; +import org.quartz.SchedulerException; +import org.quartz.Trigger; +import org.quartz.TriggerListener; +import org.quartz.impl.JobDetailImpl; + +import java.util.Properties; + +public interface Scheduler +{ + + void scheduleJob( JobDetailImpl jobDetail, Trigger trigger ) + throws SchedulerException; + + /** + * @param listener + */ + void addGlobalJobListener( JobListener listener ) + throws SchedulerException; + + /** + * @param listener + */ + void addGlobalTriggerListener( TriggerListener listener ) + throws SchedulerException; + + void unscheduleJob( String jobName, String groupName ) + throws SchedulerException; + + boolean interruptSchedule( String jobName, String groupName ) + throws SchedulerException; + + void setProperties( Properties properties ); + + Properties getProperties(); + + void shutdown( boolean waitForJobsToComplete ); + +} diff --git a/src/main/java/org/codehaus/redback/components/scheduler/configuration/SchedulerConfiguration.java b/src/main/java/org/codehaus/redback/components/scheduler/configuration/SchedulerConfiguration.java new file mode 100644 index 0000000..a340b02 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/scheduler/configuration/SchedulerConfiguration.java @@ -0,0 +1,133 @@ +package org.codehaus.redback.components.scheduler.configuration; + +/* + * 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. + */ + +import org.codehaus.redback.components.scheduler.Scheduler; +import org.quartz.impl.StdSchedulerFactory; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; + +/** + * Class to represent the configuration file for the proxy + * + * @author John Tolentino + * plexus.component role="org.codehaus.plexus.scheduler.configuration.SchedulerConfiguration" + */ +@Service +public class SchedulerConfiguration +{ + /* + * plexus.required + */ + @Inject + private Scheduler plexusScheduler; + + public String getInstanceName() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME ); + } + + public void setInstanceName( String instanceName ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, instanceName ); + } + + public String getInstanceId() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_INSTANCE_ID ); + } + + public void setInstanceId( String InstanceId ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_INSTANCE_ID, InstanceId ); + } + + public String getThreadName() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_THREAD_NAME ); + } + + public void setThreadName( String threadName ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_THREAD_NAME, threadName ); + } + + public String getIdleWaitTime() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_IDLE_WAIT_TIME ); + } + + public void setIdleWaitTime( String idleWaitTime ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_IDLE_WAIT_TIME, idleWaitTime ); + } + + public String getDbFailureRetryInterval() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_DB_FAILURE_RETRY_INTERVAL ); + } + + public void setDbFailureRetryInterval( String dbFailureRetryInterval ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_DB_FAILURE_RETRY_INTERVAL, dbFailureRetryInterval ); + } + + public String getClassLoadHelper() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_CLASS_LOAD_HELPER_CLASS ); + } + + public void setClassLoadHelper( String classLoadHelper ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_CLASS_LOAD_HELPER_CLASS, classLoadHelper ); + } + + public String getContextKey() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_CONTEXT_PREFIX ); + } + + public void setContextKey( String contextKey ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_CONTEXT_PREFIX, contextKey ); + } + + public String getUserTransactionURL() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_USER_TX_URL ); + } + + public void setUserTransactionURL( String userTransactionURL ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_USER_TX_URL, userTransactionURL ); + } + + public String getWrapJobExecutionInUserTransaction() + { + return plexusScheduler.getProperties().getProperty( StdSchedulerFactory.PROP_SCHED_WRAP_JOB_IN_USER_TX ); + } + + public void setWrapJobExecutionInUserTransaction( String wrapJobExecutionInUserTransaction ) + { + plexusScheduler.getProperties().setProperty( StdSchedulerFactory.PROP_SCHED_WRAP_JOB_IN_USER_TX, wrapJobExecutionInUserTransaction ); + } + +} diff --git a/src/main/resources/META-INF/spring-context.xml b/src/main/resources/META-INF/spring-context.xml new file mode 100755 index 0000000..04ec35b --- /dev/null +++ b/src/main/resources/META-INF/spring-context.xml @@ -0,0 +1,34 @@ +<?xml version="1.0"?> + +<!-- + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" + default-lazy-init="true"> + + <context:annotation-config /> + <context:component-scan + base-package="org.codehaus.redback.components.scheduler"/> + +</beans> \ No newline at end of file diff --git a/src/test/java/org/codehaus/redback/components/scheduler/CronExpressionValidatorTest.java b/src/test/java/org/codehaus/redback/components/scheduler/CronExpressionValidatorTest.java new file mode 100644 index 0000000..6f0f832 --- /dev/null +++ b/src/test/java/org/codehaus/redback/components/scheduler/CronExpressionValidatorTest.java @@ -0,0 +1,127 @@ +package org.codehaus.redback.components.scheduler; + +/* + * Copyright 2004-2005 The Apache Software Foundation. + * + * 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. + */ + +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import javax.inject.Inject; + +@RunWith( SpringJUnit4ClassRunner.class ) +@ContextConfiguration( locations = {"classpath*:/META-INF/spring-context.xml","classpath:/spring-context.xml"} ) +public class CronExpressionValidatorTest + extends TestCase +{ + + @Inject + CronExpressionValidator validator; + + @Test + public void testValidation() + throws Exception + { + + assertTrue( validator.validate( "0 0 * * * ?" ) ); + + assertTrue( validator.validate( "0 0 * ? * *" ) ); + + assertFalse( validator.validate( "0 0 4-1 * * ?" ) ); + + assertTrue( validator.validate( "0 0 1-4 * * ?" ) ); + + assertTrue( validator.validate( "0 0,15,30,45 * * * ?" ) ); + + assertFalse( validator.validate( "0 0,45,15,30 * * * ?" ) ); + + assertTrue( validator.validate( "0 0 12 * * ?" ) ); + + assertTrue( validator.validate( "0 15 10 ? * *" ) ); + + assertTrue( validator.validate( "0 15 10 * * ?" ) ); + + assertTrue( validator.validate( "0 15 10 * * ? *" ) ); + + assertTrue( validator.validate( "0 15 10 * * ? 2005" ) ); + + assertFalse( validator.validate( "0 15 10 * * ? 2100" ) ); + + assertFalse( validator.validate( "0 15 10 * * ? 1969" ) ); + + assertTrue( validator.validate( "0 15 10 * * ? 2005-2007" ) ); + + assertFalse( validator.validate( "0 15 10 * * ? 2005-2100" ) ); + + assertFalse( validator.validate( "0 15 10 * * ? 1960-2010" ) ); + + assertTrue( validator.validate( "0 15 10 * * ? 2005/2" ) ); + + assertFalse( validator.validate( "0 15 10 * * ? 2100/3" ) ); + + assertFalse( validator.validate( "0 15 10 * * ? 1960/10" ) ); + + assertTrue( validator.validate( "0 * 14 * * ?" ) ); + + assertTrue( validator.validate( "0 0/5 14 * * ?" ) ); + + assertTrue( validator.validate( "0 0/5 14,18 * * ?" ) ); + + assertTrue( validator.validate( "0 0-5 14 * * ?" ) ); + + assertTrue( validator.validate( "0 10,44 14 ? 3 WED" ) ); + + assertTrue( validator.validate( "0 15 10 ? * MON-FRI" ) ); + + assertTrue( validator.validate( "0 15 10 15 * ?" ) ); + + assertTrue( validator.validate( "0 15 10 L * ?" ) ); + + assertFalse( validator.validate( "0 15 10 6#3 * ?" ) ); + + assertTrue( validator.validate( "0 15 10 15W * ?" ) ); + + assertFalse( validator.validate( "0 15 10 15W1 * ?" ) ); + + assertTrue( validator.validate( "0 15 10 ? * 6L" ) ); + + assertTrue( validator.validate( "0 15 10 ? * 6L" ) ); + + assertTrue( validator.validate( "0 15 10 ? * 6L 2002-2005" ) ); + + assertFalse( validator.validate( "0 15 10 ? * 6L3 2002-2005" ) ); + + assertTrue( validator.validate( "0 15 10 ? * 6#3" ) ); + + assertFalse( validator.validate( "0 15 10 ? * 6#" ) ); + + assertFalse( validator.validate( "0 15 10 ? * #3" ) ); + + assertFalse( validator.validate( "0 15 10 ? * 8#3" ) ); + + assertFalse( validator.validate( "0 15 10 ? * 6#6" ) ); + + assertFalse( validator.validate( "0 0" ) ); + + assertFalse( validator.validate( "0 0 * * * *" ) ); + + assertFalse( validator.validate( "a a a a a a" ) ); + + assertFalse( validator.validate( "0 0 0 ? 0 A" ) ); + } +} diff --git a/src/test/java/org/codehaus/redback/components/scheduler/JobOne.java b/src/test/java/org/codehaus/redback/components/scheduler/JobOne.java new file mode 100644 index 0000000..83e6948 --- /dev/null +++ b/src/test/java/org/codehaus/redback/components/scheduler/JobOne.java @@ -0,0 +1,79 @@ +package org.codehaus.redback.components.scheduler; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, 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" and "Apache Software Foundation" and + * "Apache Turbine" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apa...@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache Turbine", 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 (INCLUDING, 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. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import java.util.Date; + +public class JobOne + implements Job +{ + public JobOne() + { + } + + public void execute( JobExecutionContext context ) + throws JobExecutionException + { + System.out.println( + " --- Testing Scheduler Component\n --- " + context.getJobDetail().getDescription() + " executed.[" + + new Date() + "]" ); + + } + +} diff --git a/src/test/java/org/codehaus/redback/components/scheduler/SchedulerTest.java b/src/test/java/org/codehaus/redback/components/scheduler/SchedulerTest.java new file mode 100644 index 0000000..58ffda9 --- /dev/null +++ b/src/test/java/org/codehaus/redback/components/scheduler/SchedulerTest.java @@ -0,0 +1,102 @@ +package org.codehaus.redback.components.scheduler; + +import junit.framework.TestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerListener; +import org.quartz.impl.JobDetailImpl; +import org.quartz.impl.triggers.SimpleTriggerImpl; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import javax.inject.Inject; + +@RunWith( SpringJUnit4ClassRunner.class ) +@ContextConfiguration( locations = {"classpath*:/META-INF/spring-context.xml","classpath:/spring-context.xml"} ) +public class SchedulerTest + extends TestCase + implements TriggerListener +{ + private boolean triggerFired; + + @Inject + private Scheduler scheduler; + + @After + public void stop() + { + scheduler.shutdown( true ); + } + + @Test + public void testCreation() + throws Exception + { + + + assertNotNull( scheduler ); + + JobDataMap dataMap = new JobDataMap(); + + dataMap.put( "project", "continuum" ); + + JobDetailImpl jobDetail = new JobDetailImpl( "job", "group", JobOne.class ); + + jobDetail.setJobDataMap( dataMap ); + + TriggerBuilder.newTrigger(); + + Trigger trigger = new SimpleTriggerImpl( "trigger", "group" ); + + scheduler.addGlobalTriggerListener( this ); + + scheduler.scheduleJob( jobDetail, trigger ); + + while ( ! triggerFired ) + { + //System.out.println("! triggerFired"); + Thread.sleep( 10 ); + } + System.out.println("ok triggerFired"); + } + + public void triggerComplete( Trigger trigger, JobExecutionContext context, int triggerInstructionCode ) + { + } + + public boolean vetoJobExecution( Trigger trigger, JobExecutionContext context ) + { + return false; + } + + public void triggerFired( Trigger trigger, JobExecutionContext context ) + { + System.out.println( "Trigger fired!" ); + + triggerFired = true; + } + + public void triggerMisfired( Trigger trigger ) + { + } + + public void triggerComplete( Trigger trigger, JobExecutionContext context, + Trigger.CompletedExecutionInstruction triggerInstructionCode ) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public String getName() + { + return "foo"; + } + + + +} + diff --git a/src/test/resources/spring-context.xml b/src/test/resources/spring-context.xml new file mode 100755 index 0000000..16ec4a1 --- /dev/null +++ b/src/test/resources/spring-context.xml @@ -0,0 +1,41 @@ +<?xml version="1.0"?> + +<!-- + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <bean name="scheduler" class="org.codehaus.redback.components.scheduler.DefaultScheduler"> + <property name="properties"> + <props> + <prop key="org.quartz.scheduler.instanceName">scheduler1</prop> + <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop> + <prop key="org.quartz.threadPool.threadCount">1</prop> + <prop key="org.quartz.threadPool.threadPriority">4</prop> + <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop> + </props> + </property> + </bean> + +</beans> \ No newline at end of file -- To stop receiving notification emails like this one, please contact marti...@apache.org.