| /** |
| * 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. |
| */ |
| |
| package org.apache.oozie.util; |
| |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.TimeZone; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.quartz.CronExpression; |
| import java.text.ParseException; |
| |
| /** |
| * Utility class to check common parameter preconditions. |
| */ |
| public class ParamChecker { |
| |
| private static final int MAX_NODE_NAME_LEN = 128; |
| |
| /** |
| * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException. |
| * |
| * @param str value. |
| * @param name parameter name for the exception message. |
| * @return the given value. |
| */ |
| public static String notEmpty(String str, String name) { |
| return notEmpty(str, name, null); |
| } |
| |
| /** |
| * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException. |
| * |
| * @param str value. |
| * @param name parameter name for the exception message. |
| * @param info additional information to be printed with the exception message |
| * @return the given value. |
| */ |
| public static String notEmpty(String str, String name, String info) { |
| if (str == null) { |
| throw new IllegalArgumentException(name + " cannot be null" + (info == null ? "" : ", " + info)); |
| } |
| if (str.length() == 0) { |
| throw new IllegalArgumentException(name + " cannot be empty" + (info == null ? "" : ", " + info)); |
| } |
| return str; |
| } |
| |
| /** |
| * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements |
| * throws an IllegalArgumentException. |
| * |
| * @param list the list of strings. |
| * @param name parameter name for the exception message. |
| * @return the given list. |
| */ |
| public static List<String> notEmptyElements(List<String> list, String name) { |
| Objects.requireNonNull(list, () -> String.format("%s cannot be null", name)); |
| for (int i = 0; i < list.size(); i++) { |
| notEmpty(list.get(i), XLog.format("list [{0}] element [{1}]", name, i)); |
| } |
| return list; |
| } |
| |
| /** |
| * Check that the given string is a valid action name [a-zA-Z_][0-9a-zA-Z_\-]* and not longer than 128 chars. |
| * |
| * @param actionName string to validate is a token. |
| * @return the given string. |
| */ |
| public static String validateActionName(String actionName) { |
| ParamChecker.notEmpty(actionName, "action name"); |
| if (actionName.length() > MAX_NODE_NAME_LEN) { |
| throw new IllegalArgumentException(XLog.format("name [{0}] must be {1} chars or less", actionName, |
| MAX_NODE_NAME_LEN)); |
| } |
| |
| char c = actionName.charAt(0); |
| if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) { |
| throw new IllegalArgumentException(XLog.format("name [{0}], must start with [A-Za-z_]", actionName)); |
| } |
| for (int i = 1; i < actionName.length(); i++) { |
| c = actionName.charAt(i); |
| if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') |
| && !(c == '_' || c == '-')) { |
| throw new IllegalArgumentException(XLog.format("name [{0}] must be [A-Za-z_][0-9A-Za-z_]*", actionName)); |
| } |
| } |
| return actionName; |
| } |
| |
| /** |
| * Return if the specified token is a valid Java identifier. |
| * |
| * @param token string to validate if it is a valid Java identifier. |
| * @return if the specified token is a valid Java identifier. |
| */ |
| public static boolean isValidIdentifier(String token) { |
| ParamChecker.notEmpty(token, "identifier"); |
| for (int i = 0; i < token.length(); i++) { |
| char c = token.charAt(i); |
| if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) { |
| return false; |
| } |
| if (i == 0 && (c >= '0' && c <= '9')) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Check whether the value is greater than or equals 0. |
| * |
| * @param value : value to test |
| * @param name : Name of the parameter |
| * @return If the value is > 0, return the value. Otherwise throw IllegalArgumentException |
| */ |
| public static int checkGTZero(int value, String name) { |
| if (value <= 0) { |
| throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be greater than zero", name, |
| value)); |
| } |
| return value; |
| } |
| |
| /** |
| * Check whether the value is greater than or equals to 0. |
| * |
| * @param value : value to test |
| * @param name : Name of the parameter |
| * @return If the value is >= 0, return the value. Otherwise throw IllegalArgumentException |
| */ |
| public static int checkGEZero(int value, String name) { |
| if (value < 0) { |
| throw new IllegalArgumentException(XLog.format( |
| "parameter [{0}] = [{1}] must be greater than or equals zero", name, value)); |
| } |
| return value; |
| } |
| |
| /** |
| * Check whether the value is less than or equal to 0. |
| * |
| * @param value : value to test |
| * @param name : Name of the parameter |
| * @return If the value is <= 0, return the value. Otherwise throw IllegalArgumentException |
| */ |
| public static int checkLEZero(int value, String name) { |
| if (value > 0) { |
| throw new IllegalArgumentException(XLog.format( |
| "parameter [{0}] = [{1}] must be less than or equal to zero", name, value)); |
| } |
| return value; |
| } |
| |
| /** |
| * Check whether the value is Integer. |
| * |
| * @param val : value to test |
| * @param name : Name of the parameter |
| * @return If the value is integer, return the value. Otherwise throw IllegalArgumentException |
| */ |
| public static int checkInteger(String val, String name) { |
| int ret; |
| try { |
| ret = Integer.parseInt(val); |
| } |
| catch (NumberFormatException nex) { |
| throw new IllegalArgumentException(XLog.format( |
| "parameter [{0}] = [{1}] must be an integer. Parsing error {2}", name, val, nex.getMessage(), nex)); |
| } |
| return ret; |
| } |
| |
| /** |
| * Check whether a value is a valid coordinator frequency. |
| * |
| * @param val : value to test |
| * @return If the value is a valid frequency, return the frequency, Otherwise throw IllegalArgumentException |
| */ |
| public static String checkFrequency(String val) { |
| try { |
| Integer.parseInt(val); |
| } |
| catch (NumberFormatException ex) { |
| try { |
| // this part is necessary since Quartz |
| // doesn't support for specifying both a day-of-week |
| // and a day-of-month parameter, nor does it support |
| // using "?" in both fields, but we don't want to |
| // expose it to users. |
| String[] cronArray1 = val.split(" "); |
| String[] cronArray2 = val.split(" "); |
| |
| if (cronArray1.length != 5) { |
| throw new IllegalArgumentException(XLog.format( |
| "parameter [{0}] = [{1}] must have 5 bit fields. Parsing error {2}", "frequency", |
| val, ex.getMessage(), ex)); |
| } |
| |
| if (!cronArray1[4].trim().equals("?")) { |
| cronArray1[2] = "?"; |
| } |
| |
| if (!cronArray2[2].trim().equals("?")) { |
| cronArray2[4] = "?"; |
| } |
| |
| new CronExpression("0 " + StringUtils.join(cronArray1, " ")); |
| new CronExpression("0 " + StringUtils.join(cronArray2, " ")); |
| } |
| catch (ParseException pex) { |
| throw new IllegalArgumentException(XLog.format( |
| "parameter [{0}] = [{1}] must be an integer or a cron syntax. Parsing error {2}", "frequency", |
| val, ex.getMessage(), ex)); |
| } |
| } |
| return val; |
| } |
| /** |
| * Check whether the value is Oozie processing timezone data format. |
| * |
| * @param date : date to test |
| * @param name : Name of the parameter |
| * @return If the value is in Oozie processing timezone date format, return the value. |
| * Otherwise throw IllegalArgumentException |
| */ |
| public static Date checkDateOozieTZ(String date, String name) { |
| Date ret; |
| try { |
| ret = DateUtils.parseDateOozieTZ(date); |
| } |
| catch (Exception ex) { |
| throw new IllegalArgumentException(XLog.format( |
| "parameter [{0}] = [{1}] must be Date in {2} format ({3})." |
| + " Parsing error {4}", name, date, DateUtils.getOozieProcessingTimeZone().getID(), |
| DateUtils.getOozieTimeMask(), ex)); |
| } |
| return ret; |
| } |
| |
| /** |
| * Check whether the value mention correct Timezone. |
| * |
| * @param tzStr : timezone to test |
| * @param name : Name of the parameter |
| * @return If the value is correct TZ return the value. Otherwise throw IllegalArgumentException |
| */ |
| public static TimeZone checkTimeZone(String tzStr, String name) { |
| TimeZone tz; |
| try { |
| tz = DateUtils.getTimeZone(tzStr); |
| } |
| catch (Exception ex) { |
| throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be a valid TZ." |
| + " Parsing error {2}", name, tzStr, ex.getMessage(), ex)); |
| } |
| return tz; |
| } |
| |
| /** |
| * Check whether an item is a member of an array of string |
| * |
| * @param item : item to test |
| * @param members : List of items in string |
| * @param name : Name of the parameter |
| * @return If the item is in the member return true. Otherwise throw IllegalArgumentException |
| */ |
| public static boolean isMember(String item, String[] members, String name) { |
| for (int i = 0; i < members.length; i++) { |
| if (members[i].equals(item)) { |
| return true; |
| } |
| } |
| // Error case |
| StringBuilder buff = new StringBuilder(); |
| for (int i = 0; i < members.length; i++) { |
| buff.append(members[i]).append(", "); |
| } |
| throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] " + "must be in the list {2}", name, |
| item, buff.toString())); |
| } |
| } |