001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.util; 020 021import java.util.Date; 022import java.util.List; 023import java.util.TimeZone; 024 025import org.apache.commons.lang.StringUtils; 026import org.quartz.CronExpression; 027import java.text.ParseException; 028 029/** 030 * Utility class to check common parameter preconditions. 031 */ 032public class ParamChecker { 033 034 /** 035 * Check that a value is not null. If null throws an IllegalArgumentException. 036 * 037 * @param obj value. 038 * @param name parameter name for the exception message. 039 * @return the given value. 040 */ 041 public static <T> T notNull(T obj, String name) { 042 if (obj == null) { 043 throw new IllegalArgumentException(name + " cannot be null"); 044 } 045 return obj; 046 } 047 048 /** 049 * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements 050 * throws an IllegalArgumentException. 051 * 052 * @param list the list of strings. 053 * @param name parameter name for the exception message. 054 * @return the given list. 055 */ 056 public static <T> List<T> notNullElements(List<T> list, String name) { 057 notNull(list, name); 058 for (int i = 0; i < list.size(); i++) { 059 notNull(list.get(i), XLog.format("list [{0}] element [{1}]", name, i)); 060 } 061 return list; 062 } 063 064 /** 065 * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException. 066 * 067 * @param str value. 068 * @param name parameter name for the exception message. 069 * @return the given value. 070 */ 071 public static String notEmpty(String str, String name) { 072 return notEmpty(str, name, null); 073 } 074 075 /** 076 * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException. 077 * 078 * @param str value. 079 * @param name parameter name for the exception message. 080 * @param info additional information to be printed with the exception message 081 * @return the given value. 082 */ 083 public static String notEmpty(String str, String name, String info) { 084 if (str == null) { 085 throw new IllegalArgumentException(name + " cannot be null" + (info == null ? "" : ", " + info)); 086 } 087 if (str.length() == 0) { 088 throw new IllegalArgumentException(name + " cannot be empty" + (info == null ? "" : ", " + info)); 089 } 090 return str; 091 } 092 093 /** 094 * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements 095 * throws an IllegalArgumentException. 096 * 097 * @param list the list of strings. 098 * @param name parameter name for the exception message. 099 * @return the given list. 100 */ 101 public static List<String> notEmptyElements(List<String> list, String name) { 102 notNull(list, name); 103 for (int i = 0; i < list.size(); i++) { 104 notEmpty(list.get(i), XLog.format("list [{0}] element [{1}]", name, i)); 105 } 106 return list; 107 } 108 109 private static final int MAX_NODE_NAME_LEN = 50; 110 111 /** 112 * Check that the given string is a valid action name [a-zA-Z_][0-9a-zA-Z_\-]* and not longer than 50 chars. 113 * 114 * @param actionName string to validate is a token. 115 * @return the given string. 116 */ 117 public static String validateActionName(String actionName) { 118 ParamChecker.notEmpty(actionName, "action name"); 119 if (actionName.length() > MAX_NODE_NAME_LEN) { 120 throw new IllegalArgumentException(XLog.format("name [{0}] must be {1} chars or less", actionName, 121 MAX_NODE_NAME_LEN)); 122 } 123 124 char c = actionName.charAt(0); 125 if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) { 126 throw new IllegalArgumentException(XLog.format("name [{0}], must start with [A-Za-z_]", actionName)); 127 } 128 for (int i = 1; i < actionName.length(); i++) { 129 c = actionName.charAt(i); 130 if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') 131 && !(c == '_' || c == '-')) { 132 throw new IllegalArgumentException(XLog.format("name [{0}] must be [A-Za-z_][0-9A-Za-z_]*", actionName)); 133 } 134 } 135 return actionName; 136 } 137 138 /** 139 * Return if the specified token is a valid Java identifier. 140 * 141 * @param token string to validate if it is a valid Java identifier. 142 * @return if the specified token is a valid Java identifier. 143 */ 144 public static boolean isValidIdentifier(String token) { 145 ParamChecker.notEmpty(token, "identifier"); 146 for (int i = 0; i < token.length(); i++) { 147 char c = token.charAt(i); 148 if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) { 149 return false; 150 } 151 if (i == 0 && (c >= '0' && c <= '9')) { 152 return false; 153 } 154 } 155 return true; 156 } 157 158 /** 159 * Check whether the value is greater than or equals 0. 160 * 161 * @param value : value to test 162 * @param name : Name of the parameter 163 * @return If the value is > 0, return the value. Otherwise throw IllegalArgumentException 164 */ 165 public static int checkGTZero(int value, String name) { 166 if (value <= 0) { 167 throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be greater than zero", name, 168 value)); 169 } 170 return value; 171 } 172 173 /** 174 * Check whether the value is greater than or equals to 0. 175 * 176 * @param value : value to test 177 * @param name : Name of the parameter 178 * @return If the value is >= 0, return the value. Otherwise throw IllegalArgumentException 179 */ 180 public static int checkGEZero(int value, String name) { 181 if (value < 0) { 182 throw new IllegalArgumentException(XLog.format( 183 "parameter [{0}] = [{1}] must be greater than or equals zero", name, value)); 184 } 185 return value; 186 } 187 188 /** 189 * Check whether the value is less than or equal to 0. 190 * 191 * @param value : value to test 192 * @param name : Name of the parameter 193 * @return If the value is <= 0, return the value. Otherwise throw IllegalArgumentException 194 */ 195 public static int checkLEZero(int value, String name) { 196 if (value > 0) { 197 throw new IllegalArgumentException(XLog.format( 198 "parameter [{0}] = [{1}] must be less than or equal to zero", name, value)); 199 } 200 return value; 201 } 202 203 /** 204 * Check whether the value is Integer. 205 * 206 * @param value : value to test 207 * @param name : Name of the parameter 208 * @return If the value is integer, return the value. Otherwise throw IllegalArgumentException 209 */ 210 public static int checkInteger(String val, String name) { 211 int ret; 212 try { 213 ret = Integer.parseInt(val); 214 } 215 catch (NumberFormatException nex) { 216 throw new IllegalArgumentException(XLog.format( 217 "parameter [{0}] = [{1}] must be an integer. Parsing error {2}", name, val, nex.getMessage(), nex)); 218 } 219 return ret; 220 } 221 222 /** 223 * Check whether a value is a valid coordinator frequency. 224 * 225 * @param value : value to test 226 * @return If the value is a valid frequency, return the frequency, Otherwise throw IllegalArgumentException 227 */ 228 public static String checkFrequency(String val) { 229 try { 230 Integer.parseInt(val); 231 } 232 catch (NumberFormatException ex) { 233 try { 234 // this part is necessary since Quartz 235 // doesn't support for specifying both a day-of-week 236 // and a day-of-month parameter, nor does it support 237 // using "?" in both fields, but we don't want to 238 // expose it to users. 239 String[] cronArray1 = val.split(" "); 240 String[] cronArray2 = val.split(" "); 241 242 if (cronArray1.length != 5) { 243 throw new IllegalArgumentException(XLog.format( 244 "parameter [{0}] = [{1}] must have 5 bit fields. Parsing error {2}", "frequency", 245 val, ex.getMessage(), ex)); 246 } 247 248 if (!cronArray1[4].trim().equals("?")) { 249 cronArray1[2] = "?"; 250 } 251 252 if (!cronArray2[2].trim().equals("?")) { 253 cronArray2[4] = "?"; 254 } 255 256 new CronExpression("0 " + StringUtils.join(cronArray1, " ")); 257 new CronExpression("0 " + StringUtils.join(cronArray2, " ")); 258 } 259 catch (ParseException pex) { 260 throw new IllegalArgumentException(XLog.format( 261 "parameter [{0}] = [{1}] must be an integer or a cron syntax. Parsing error {2}", "frequency", 262 val, ex.getMessage(), ex)); 263 } 264 } 265 return val; 266 } 267 /** 268 * Check whether the value is Oozie processing timezone data format. 269 * 270 * @param value : value to test 271 * @param name : Name of the parameter 272 * @return If the value is in Oozie processing timezone date format, return the value. 273 * Otherwise throw IllegalArgumentException 274 */ 275 public static Date checkDateOozieTZ(String date, String name) { 276 Date ret; 277 try { 278 ret = DateUtils.parseDateOozieTZ(date); 279 } 280 catch (Exception ex) { 281 throw new IllegalArgumentException(XLog.format( 282 "parameter [{0}] = [{1}] must be Date in {2} format ({3})." 283 + " Parsing error {4}", name, date, DateUtils.getOozieProcessingTimeZone().getID(), 284 DateUtils.getOozieTimeMask(), ex)); 285 } 286 return ret; 287 } 288 289 /** 290 * Check whether the value mention correct Timezone. 291 * 292 * @param value : value to test 293 * @param name : Name of the parameter 294 * @return If the value is correct TZ return the value. Otherwise throw IllegalArgumentException 295 */ 296 public static TimeZone checkTimeZone(String tzStr, String name) { 297 TimeZone tz; 298 try { 299 tz = DateUtils.getTimeZone(tzStr); 300 } 301 catch (Exception ex) { 302 throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be a valid TZ." 303 + " Parsing error {2}", name, tzStr, ex.getMessage(), ex)); 304 } 305 return tz; 306 } 307 308 /** 309 * Check whether an item is a member of an array of string 310 * 311 * @param item : item to test 312 * @param members : List of items in string 313 * @param name : Name of the parameter 314 * @return If the item is in the member return true. Otherwise throw IllegalArgumentException 315 */ 316 public static boolean isMember(String item, String[] members, String name) { 317 for (int i = 0; i < members.length; i++) { 318 if (members[i].equals(item)) { 319 return true; 320 } 321 } 322 // Error case 323 StringBuilder buff = new StringBuilder(); 324 for (int i = 0; i < members.length; i++) { 325 buff.append(members[i]).append(", "); 326 } 327 throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] " + "must be in the list {2}", name, 328 item, buff.toString())); 329 } 330}