CronSequenceGenerator.isValidExpression actually validates cron fields
Issue: SPR-15604
This commit is contained in:
parent
cc74a2891a
commit
5f4d1a4628
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.scheduling.support;
|
package org.springframework.scheduling.support;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -26,6 +25,7 @@ import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,6 +50,7 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Ruslan Sibgatullin
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see CronTrigger
|
* @see CronTrigger
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +58,7 @@ public class CronSequenceGenerator {
|
||||||
|
|
||||||
private final String expression;
|
private final String expression;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private final TimeZone timeZone;
|
private final TimeZone timeZone;
|
||||||
|
|
||||||
private final BitSet months = new BitSet(12);
|
private final BitSet months = new BitSet(12);
|
||||||
|
@ -96,6 +98,12 @@ public class CronSequenceGenerator {
|
||||||
parse(expression);
|
parse(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CronSequenceGenerator(String expression, String[] fields) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.timeZone = null;
|
||||||
|
doParse(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the cron pattern that this sequence generator has been built for.
|
* Return the cron pattern that this sequence generator has been built for.
|
||||||
|
@ -234,7 +242,7 @@ public class CronSequenceGenerator {
|
||||||
// roll over if needed
|
// roll over if needed
|
||||||
if (nextValue == -1) {
|
if (nextValue == -1) {
|
||||||
calendar.add(nextField, 1);
|
calendar.add(nextField, 1);
|
||||||
reset(calendar, Arrays.asList(field));
|
reset(calendar, Collections.singletonList(field));
|
||||||
nextValue = bits.nextSetBit(0);
|
nextValue = bits.nextSetBit(0);
|
||||||
}
|
}
|
||||||
if (nextValue != value) {
|
if (nextValue != value) {
|
||||||
|
@ -265,12 +273,17 @@ public class CronSequenceGenerator {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
"Cron expression must consist of 6 fields (found %d in \"%s\")", fields.length, expression));
|
"Cron expression must consist of 6 fields (found %d in \"%s\")", fields.length, expression));
|
||||||
}
|
}
|
||||||
|
doParse(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doParse(String[] fields) {
|
||||||
setNumberHits(this.seconds, fields[0], 0, 60);
|
setNumberHits(this.seconds, fields[0], 0, 60);
|
||||||
setNumberHits(this.minutes, fields[1], 0, 60);
|
setNumberHits(this.minutes, fields[1], 0, 60);
|
||||||
setNumberHits(this.hours, fields[2], 0, 24);
|
setNumberHits(this.hours, fields[2], 0, 24);
|
||||||
setDaysOfMonth(this.daysOfMonth, fields[3]);
|
setDaysOfMonth(this.daysOfMonth, fields[3]);
|
||||||
setMonths(this.months, fields[4]);
|
setMonths(this.months, fields[4]);
|
||||||
setDays(this.daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8);
|
setDays(this.daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8);
|
||||||
|
|
||||||
if (this.daysOfWeek.get(7)) {
|
if (this.daysOfWeek.get(7)) {
|
||||||
// Sunday can be represented as 0 or 7
|
// Sunday can be represented as 0 or 7
|
||||||
this.daysOfWeek.set(0);
|
this.daysOfWeek.set(0);
|
||||||
|
@ -388,19 +401,29 @@ public class CronSequenceGenerator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the specified expression represents a valid cron pattern.
|
* Determine whether the specified expression represents a valid cron pattern.
|
||||||
* <p>Specifically, this method verifies that the expression contains six
|
|
||||||
* fields separated by single spaces.
|
|
||||||
* @param expression the expression to evaluate
|
* @param expression the expression to evaluate
|
||||||
* @return {@code true} if the given expression is a valid cron expression
|
* @return {@code true} if the given expression is a valid cron expression
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public static boolean isValidExpression(String expression) {
|
public static boolean isValidExpression(@Nullable String expression) {
|
||||||
|
if (expression == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
String[] fields = StringUtils.tokenizeToStringArray(expression, " ");
|
String[] fields = StringUtils.tokenizeToStringArray(expression, " ");
|
||||||
return areValidCronFields(fields);
|
if (!areValidCronFields(fields)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
new CronSequenceGenerator(expression, fields);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean areValidCronFields(String[] fields) {
|
private static boolean areValidCronFields(@Nullable String[] fields) {
|
||||||
return (fields.length == 6);
|
return (fields != null && fields.length == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -24,6 +24,7 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Ruslan Sibgatullin
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class CronSequenceGeneratorTests {
|
public class CronSequenceGeneratorTests {
|
||||||
|
@ -82,10 +83,20 @@ public class CronSequenceGeneratorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidExpression() {
|
public void invalidExpressionWithLength() {
|
||||||
assertFalse(CronSequenceGenerator.isValidExpression("0 */2 1-4 * * * *"));
|
assertFalse(CronSequenceGenerator.isValidExpression("0 */2 1-4 * * * *"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidExpressionWithSeconds() {
|
||||||
|
assertFalse(CronSequenceGenerator.isValidExpression("100 */2 1-4 * * *"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidExpressionWithMonths() {
|
||||||
|
assertFalse(CronSequenceGenerator.isValidExpression("0 */2 1-4 * INVALID *"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nullExpression() {
|
public void nullExpression() {
|
||||||
assertFalse(CronSequenceGenerator.isValidExpression(null));
|
assertFalse(CronSequenceGenerator.isValidExpression(null));
|
||||||
|
|
Loading…
Reference in New Issue