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 */
018package org.apache.oozie.util;
019
020import java.util.Date;
021import java.util.List;
022import java.util.TimeZone;
023
024/**
025 * Utility class to check common parameter preconditions.
026 */
027public class ParamChecker {
028
029    /**
030     * Check that a value is not null. If null throws an IllegalArgumentException.
031     *
032     * @param obj value.
033     * @param name parameter name for the exception message.
034     * @return the given value.
035     */
036    public static <T> T notNull(T obj, String name) {
037        if (obj == null) {
038            throw new IllegalArgumentException(name + " cannot be null");
039        }
040        return obj;
041    }
042
043    /**
044     * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements
045     * throws an IllegalArgumentException.
046     *
047     * @param list the list of strings.
048     * @param name parameter name for the exception message.
049     * @return the given list.
050     */
051    public static <T> List<T> notNullElements(List<T> list, String name) {
052        notNull(list, name);
053        for (int i = 0; i < list.size(); i++) {
054            notNull(list.get(i), XLog.format("list [{0}] element [{1}]", name, i));
055        }
056        return list;
057    }
058
059    /**
060     * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException.
061     *
062     * @param str value.
063     * @param name parameter name for the exception message.
064     * @return the given value.
065     */
066    public static String notEmpty(String str, String name) {
067        return notEmpty(str, name, null);
068    }
069
070    /**
071     * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException.
072     *
073     * @param str value.
074     * @param name parameter name for the exception message.
075     * @param info additional information to be printed with the exception message
076     * @return the given value.
077     */
078    public static String notEmpty(String str, String name, String info) {
079        if (str == null) {
080            throw new IllegalArgumentException(name + " cannot be null" + (info == null ? "" : ", " + info));
081        }
082        if (str.length() == 0) {
083            throw new IllegalArgumentException(name + " cannot be empty" + (info == null ? "" : ", " + info));
084        }
085        return str;
086    }
087
088    /**
089     * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements
090     * throws an IllegalArgumentException.
091     *
092     * @param list the list of strings.
093     * @param name parameter name for the exception message.
094     * @return the given list.
095     */
096    public static List<String> notEmptyElements(List<String> list, String name) {
097        notNull(list, name);
098        for (int i = 0; i < list.size(); i++) {
099            notEmpty(list.get(i), XLog.format("list [{0}] element [{1}]", name, i));
100        }
101        return list;
102    }
103
104    private static final int MAX_NODE_NAME_LEN = 50;
105
106    /**
107     * Check that the given string is a valid action name [a-zA-Z_][0-9a-zA-Z_\-]* and not longer than 50 chars.
108     *
109     * @param actionName string to validate is a token.
110     * @return the given string.
111     */
112    public static String validateActionName(String actionName) {
113        ParamChecker.notEmpty(actionName, "action name");
114        if (actionName.length() > MAX_NODE_NAME_LEN) {
115            throw new IllegalArgumentException(XLog.format("name [{0}] must be {1} chars or less", actionName,
116                                                           MAX_NODE_NAME_LEN));
117        }
118
119        char c = actionName.charAt(0);
120        if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) {
121            throw new IllegalArgumentException(XLog.format("name [{0}], must start with [A-Za-z_]", actionName));
122        }
123        for (int i = 1; i < actionName.length(); i++) {
124            c = actionName.charAt(i);
125            if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z')
126                    && !(c == '_' || c == '-')) {
127                throw new IllegalArgumentException(XLog.format("name [{0}] must be [A-Za-z_][0-9A-Za-z_]*", actionName));
128            }
129        }
130        return actionName;
131    }
132
133    /**
134     * Return if the specified token is a valid Java identifier.
135     *
136     * @param token string to validate if it is a valid Java identifier.
137     * @return if the specified token is a valid Java identifier.
138     */
139    public static boolean isValidIdentifier(String token) {
140        ParamChecker.notEmpty(token, "identifier");
141        for (int i = 0; i < token.length(); i++) {
142            char c = token.charAt(i);
143            if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) {
144                return false;
145            }
146            if (i == 0 && (c >= '0' && c <= '9')) {
147                return false;
148            }
149        }
150        return true;
151    }
152
153    /**
154     * Check whether the value is greater than or equals 0.
155     *
156     * @param value : value to test
157     * @param name : Name of the parameter
158     * @return If the value is > 0, return the value. Otherwise throw IllegalArgumentException
159     */
160    public static int checkGTZero(int value, String name) {
161        if (value <= 0) {
162            throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be greater than zero", name,
163                                                           value));
164        }
165        return value;
166    }
167
168    /**
169     * Check whether the value is greater than or equals to 0.
170     *
171     * @param value : value to test
172     * @param name : Name of the parameter
173     * @return If the value is >= 0, return the value. Otherwise throw IllegalArgumentException
174     */
175    public static int checkGEZero(int value, String name) {
176        if (value < 0) {
177            throw new IllegalArgumentException(XLog.format(
178                    "parameter [{0}] = [{1}] must be greater than or equals zero", name, value));
179        }
180        return value;
181    }
182
183    /**
184     * Check whether the value is less than or equal to 0.
185     *
186     * @param value : value to test
187     * @param name : Name of the parameter
188     * @return If the value is <= 0, return the value. Otherwise throw IllegalArgumentException
189     */
190    public static int checkLEZero(int value, String name) {
191        if (value > 0) {
192            throw new IllegalArgumentException(XLog.format(
193                    "parameter [{0}] = [{1}] must be less than or equal to zero", name, value));
194        }
195        return value;
196    }
197
198    /**
199     * Check whether the value is Integer.
200     *
201     * @param value : value to test
202     * @param name : Name of the parameter
203     * @return If the value is integer, return the value. Otherwise throw IllegalArgumentException
204     */
205    public static int checkInteger(String val, String name) {
206        int ret;
207        try {
208            ret = Integer.parseInt(val);
209        }
210        catch (NumberFormatException nex) {
211            throw new IllegalArgumentException(XLog.format(
212                    "parameter [{0}] = [{1}]  must be an integer. Parsing error {2}", name, val, nex.getMessage(), nex));
213        }
214        return ret;
215    }
216
217    /**
218     * Check whether the value is Oozie processing timezone data format.
219     *
220     * @param value : value to test
221     * @param name : Name of the parameter
222     * @return If the value is in Oozie processing timezone date format, return the value.
223     * Otherwise throw IllegalArgumentException
224     */
225    public static Date checkDateOozieTZ(String date, String name) {
226        Date ret;
227        try {
228            ret = DateUtils.parseDateOozieTZ(date);
229        }
230        catch (Exception ex) {
231            throw new IllegalArgumentException(XLog.format(
232                    "parameter [{0}] = [{1}] must be Date in {2} format ({3})."
233                            + " Parsing error {4}", name, date, DateUtils.getOozieProcessingTimeZone().getID(),
234                    DateUtils.getOozieTimeMask(), ex));
235        }
236        return ret;
237    }
238
239    /**
240     * Check whether the value mention correct Timezone.
241     *
242     * @param value : value to test
243     * @param name : Name of the parameter
244     * @return If the value is correct TZ return the value. Otherwise throw IllegalArgumentException
245     */
246    public static TimeZone checkTimeZone(String tzStr, String name) {
247        TimeZone tz;
248        try {
249            tz = DateUtils.getTimeZone(tzStr);
250        }
251        catch (Exception ex) {
252            throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be a valid TZ."
253                    + " Parsing error {2}", name, tzStr, ex.getMessage(), ex));
254        }
255        return tz;
256    }
257
258    /**
259     * Check whether an item is a member of an array of string
260     *
261     * @param item : item to test
262     * @param members : List of items in string
263     * @param name : Name of the parameter
264     * @return If the item is in the member return true. Otherwise throw IllegalArgumentException
265     */
266    public static boolean isMember(String item, String[] members, String name) {
267        for (int i = 0; i < members.length; i++) {
268            if (members[i].equals(item)) {
269                return true;
270            }
271        }
272        // Error case
273        StringBuilder buff = new StringBuilder();
274        for (int i = 0; i < members.length; i++) {
275            buff.append(members[i]).append(", ");
276        }
277        throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] " + "must be in the list {2}", name,
278                                                       item, buff.toString()));
279    }
280}