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    package org.apache.oozie.util;
019    
020    import java.util.Date;
021    import java.util.List;
022    import java.util.TimeZone;
023    
024    /**
025     * Utility class to check common parameter preconditions.
026     */
027    public 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            if (str == null) {
068                throw new IllegalArgumentException(name + " cannot be null");
069            }
070            if (str.length() == 0) {
071                throw new IllegalArgumentException(name + " cannot be empty");
072            }
073            return str;
074        }
075    
076        /**
077         * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements
078         * throws an IllegalArgumentException.
079         *
080         * @param list the list of strings.
081         * @param name parameter name for the exception message.
082         * @return the given list.
083         */
084        public static List<String> notEmptyElements(List<String> list, String name) {
085            notNull(list, name);
086            for (int i = 0; i < list.size(); i++) {
087                notEmpty(list.get(i), XLog.format("list [{0}] element [{1}]", name, i));
088            }
089            return list;
090        }
091    
092        private static final int MAX_NODE_NAME_LEN = 50;
093    
094        /**
095         * Check that the given string is a valid action name [a-zA-Z_][0-9a-zA-Z_\-]* and not longer than 50 chars.
096         *
097         * @param actionName string to validate is a token.
098         * @return the given string.
099         */
100        public static String validateActionName(String actionName) {
101            ParamChecker.notEmpty(actionName, "action name");
102            if (actionName.length() > MAX_NODE_NAME_LEN) {
103                throw new IllegalArgumentException(XLog.format("name [{0}] must be {1} chars or less", actionName,
104                                                               MAX_NODE_NAME_LEN));
105            }
106    
107            char c = actionName.charAt(0);
108            if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) {
109                throw new IllegalArgumentException(XLog.format("name [{0}], must start with [A-Za-z_]", actionName));
110            }
111            for (int i = 1; i < actionName.length(); i++) {
112                c = actionName.charAt(i);
113                if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z')
114                        && !(c == '_' || c == '-')) {
115                    throw new IllegalArgumentException(XLog.format("name [{0}] must be [A-Za-z_][0-9A-Za-z_]*", actionName));
116                }
117            }
118            return actionName;
119        }
120    
121        /**
122         * Return if the specified token is a valid Java identifier.
123         *
124         * @param token string to validate if it is a valid Java identifier.
125         * @return if the specified token is a valid Java identifier.
126         */
127        public static boolean isValidIdentifier(String token) {
128            ParamChecker.notEmpty(token, "identifier");
129            for (int i = 0; i < token.length(); i++) {
130                char c = token.charAt(i);
131                if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) {
132                    return false;
133                }
134                if (i == 0 && (c >= '0' && c <= '9')) {
135                    return false;
136                }
137            }
138            return true;
139        }
140    
141        /**
142         * Check whether the value is greater than or equals 0.
143         *
144         * @param value : value to test
145         * @param name : Name of the parameter
146         * @return If the value is > 0, return the value. Otherwise throw IllegalArgumentException
147         */
148        public static int checkGTZero(int value, String name) {
149            if (value <= 0) {
150                throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be greater than zero", name,
151                                                               value));
152            }
153            return value;
154        }
155    
156        /**
157         * Check whether the value is greater than or equals to 0.
158         *
159         * @param value : value to test
160         * @param name : Name of the parameter
161         * @return If the value is >= 0, return the value. Otherwise throw IllegalArgumentException
162         */
163        public static int checkGEZero(int value, String name) {
164            if (value < 0) {
165                throw new IllegalArgumentException(XLog.format(
166                        "parameter [{0}] = [{1}] must be greater than or equals zero", name, value));
167            }
168            return value;
169        }
170    
171        /**
172         * Check whether the value is Integer.
173         *
174         * @param value : value to test
175         * @param name : Name of the parameter
176         * @return If the value is integer, return the value. Otherwise throw IllegalArgumentException
177         */
178        public static int checkInteger(String val, String name) {
179            int ret;
180            try {
181                ret = Integer.parseInt(val);
182            }
183            catch (NumberFormatException nex) {
184                throw new IllegalArgumentException(XLog.format(
185                        "parameter [{0}] = [{1}]  must be an integer. Parsing error {2}", name, val, nex));
186            }
187            return ret;
188        }
189    
190        /**
191         * Check whether the value is UTC data format.
192         *
193         * @param value : value to test
194         * @param name : Name of the parameter
195         * @return If the value is in UTC date format, return the value. Otherwise throw IllegalArgumentException
196         */
197        public static Date checkUTC(String date, String name) {
198            Date ret;
199            try {
200                ret = DateUtils.parseDateUTC(date);
201            }
202            catch (Exception ex) {
203                throw new IllegalArgumentException(XLog.format(
204                        "parameter [{0}] = [{1}] must be Date in UTC format (yyyy-MM-dd'T'HH:mm'Z')."
205                                + " Parsing error {2}", name, date, ex));
206            }
207            return ret;
208        }
209    
210        /**
211         * Check whether the value mention correct Timezone.
212         *
213         * @param value : value to test
214         * @param name : Name of the parameter
215         * @return If the value is correct TZ return the value. Otherwise throw IllegalArgumentException
216         */
217        public static TimeZone checkTimeZone(String tzStr, String name) {
218            TimeZone tz;
219            try {
220                tz = DateUtils.getTimeZone(tzStr);
221            }
222            catch (Exception ex) {
223                throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] must be a valid TZ."
224                        + " Parsing error {2}", name, tzStr, ex));
225            }
226            return tz;
227        }
228    
229        /**
230         * Check whether an item is a member of an array of string
231         *
232         * @param item : item to test
233         * @param members : List of items in string
234         * @param name : Name of the parameter
235         * @return If the item is in the member return true. Otherwise throw IllegalArgumentException
236         */
237        public static boolean isMember(String item, String[] members, String name) {
238            for (int i = 0; i < members.length; i++) {
239                if (members[i].equals(item)) {
240                    return true;
241                }
242            }
243            // Error case
244            StringBuilder buff = new StringBuilder();
245            for (int i = 0; i < members.length; i++) {
246                buff.append(members[i]).append(", ");
247            }
248            throw new IllegalArgumentException(XLog.format("parameter [{0}] = [{1}] " + "must be in the list {2}", name,
249                                                           item, buff.toString()));
250        }
251    }