| | |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.task; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | |
| | | import java.util.List; |
| | | |
| | | import java.util.StringTokenizer; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.Attribute; |
| | |
| | | */ |
| | | private static enum TaskTab {MINUTE, HOUR, DAY, MONTH, WEEKDAY}; |
| | | |
| | | private final static int MINUTE_INDEX = 0; |
| | | private final static int HOUR_INDEX = 1; |
| | | private final static int DAY_INDEX = 2; |
| | | private final static int MONTH_INDEX = 3; |
| | | private final static int WEEKDAY_INDEX = 4; |
| | | private static final int MINUTE_INDEX = 0; |
| | | private static final int HOUR_INDEX = 1; |
| | | private static final int DAY_INDEX = 2; |
| | | private static final int MONTH_INDEX = 3; |
| | | private static final int WEEKDAY_INDEX = 4; |
| | | |
| | | // Wildcard match pattern. |
| | | private static final Pattern wildcardPattern = Pattern.compile("^\\*(?:/(\\d+))?"); |
| | | |
| | | // Exact match pattern. |
| | | private static final Pattern exactPattern = |
| | | Pattern.compile("\\d+"); |
| | | private static final Pattern exactPattern = Pattern.compile("(\\d+)"); |
| | | |
| | | // Range match pattern. |
| | | private static final Pattern rangePattern = |
| | | Pattern.compile("\\d+[-]\\d+"); |
| | | |
| | | // List match pattern. |
| | | private static final Pattern listPattern = |
| | | Pattern.compile("^(\\d+,)(.*)(\\d+)$"); |
| | | private static final Pattern rangePattern = Pattern.compile("(\\d+)-(\\d+)(?:/(\\d+))?"); |
| | | |
| | | // Boolean arrays holding task tab slots. |
| | | private final boolean[] minutesArray; |
| | |
| | | |
| | | /** |
| | | * Parse and validate recurring task schedule field. |
| | | * |
| | | * @param tabField recurring task schedule field in crontab(5) format. |
| | | * @param minValue minimum value allowed for this field. |
| | | * @param maxValue maximum value allowed for this field. |
| | |
| | | boolean[] valueList = new boolean[maxValue + 1]; |
| | | Arrays.fill(valueList, false); |
| | | |
| | | // Blanket. |
| | | if (tabField.equals("*")) { |
| | | for (int i = minValue; i <= maxValue; i++) { |
| | | valueList[i] = true; |
| | | } |
| | | return valueList; |
| | | } |
| | | |
| | | // Exact. |
| | | if (exactPattern.matcher(tabField).matches()) { |
| | | int value = Integer.parseInt(tabField); |
| | | if ((value >= minValue) && (value <= maxValue)) { |
| | | valueList[value] = true; |
| | | return valueList; |
| | | } |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | |
| | | // Range. |
| | | if (rangePattern.matcher(tabField).matches()) { |
| | | StringTokenizer st = new StringTokenizer(tabField, "-"); |
| | | int startValue = Integer.parseInt(st.nextToken()); |
| | | int endValue = Integer.parseInt(st.nextToken()); |
| | | if ((startValue < endValue) && |
| | | ((startValue >= minValue) && (endValue <= maxValue))) |
| | | // Wildcard with optional increment. |
| | | Matcher m = wildcardPattern.matcher(tabField); |
| | | if (m.matches() && m.groupCount() == 1) |
| | | { |
| | | for (int i = startValue; i <= endValue; i++) { |
| | | String stepString = m.group(1); |
| | | int increment = isValueAbsent(stepString) ? 1 : Integer.parseInt(stepString); |
| | | for (int i = minValue; i <= maxValue; i += increment) |
| | | { |
| | | valueList[i] = true; |
| | | } |
| | | return valueList; |
| | | } |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | |
| | | // List. |
| | | if (listPattern.matcher(tabField).matches()) { |
| | | StringTokenizer st = new StringTokenizer(tabField, ","); |
| | | while (st.hasMoreTokens()) { |
| | | int value = Integer.parseInt(st.nextToken()); |
| | | if ((value >= minValue) && (value <= maxValue)) { |
| | | valueList[value] = true; |
| | | } else { |
| | | for (String listVal : tabField.split(",")) |
| | | { |
| | | // Single number. |
| | | m = exactPattern.matcher(listVal); |
| | | if (m.matches() && m.groupCount() == 1) |
| | | { |
| | | String exactValue = m.group(1); |
| | | if (isValueAbsent(exactValue)) |
| | | { |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | int value = Integer.parseInt(exactValue); |
| | | if (value < minValue || value > maxValue) |
| | | { |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | valueList[value] = true; |
| | | continue; |
| | | } |
| | | |
| | | // Range of numbers with optional increment. |
| | | m = rangePattern.matcher(listVal); |
| | | if (m.matches() && m.groupCount() == 3) { |
| | | String startString = m.group(1); |
| | | String endString = m.group(2); |
| | | String stepString = m.group(3); |
| | | int increment = isValueAbsent(stepString) ? 1 : Integer.parseInt(stepString); |
| | | if (isValueAbsent(startString) || isValueAbsent(endString)) |
| | | { |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | int startValue = Integer.parseInt(startString); |
| | | int endValue = Integer.parseInt(endString); |
| | | if (startValue > endValue || startValue < minValue || endValue > maxValue) |
| | | { |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | for (int i = startValue; i <= endValue; i += increment) |
| | | { |
| | | valueList[i] = true; |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | // Can only have a list of numbers and ranges. |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | |
| | | return valueList; |
| | | } |
| | | |
| | | throw new IllegalArgumentException(); |
| | | /** |
| | | * Check if a String from a Matcher group is absent. Matcher returns empty strings |
| | | * for optional groups that are absent. |
| | | * |
| | | * @param s A string returned from Matcher.group() |
| | | * @return true if the string is unusable, false if it is usable. |
| | | */ |
| | | private static boolean isValueAbsent(String s) |
| | | { |
| | | return (s == null || s.length() == 0) ? true : false; |
| | | } |
| | | |
| | | /** |
| | | * Get next recurring slot from the range. |
| | | * @param timesList the range. |