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 org.apache.hadoop.conf.Configuration;
021    import org.jdom.Element;
022    import org.json.JSONObject;
023    
024    import java.text.SimpleDateFormat;
025    import java.util.Map;
026    import java.util.Properties;
027    import java.util.TimeZone;
028    import java.util.Date;
029    import java.net.URLEncoder;
030    import java.io.UnsupportedEncodingException;
031    
032    /**
033     * Base EL constants and functions.
034     */
035    public class ELConstantsFunctions {
036    
037        /**
038         * KiloByte constant (1024). Defined for EL as 'KB'.
039         */
040        public static final long KB = 1024;
041    
042        /**
043         * MegaByte constant (1024 KB). Defined for EL as 'MB'.
044         */
045        public static final long MB = KB * 1024;
046    
047        /**
048         * GigaByte constant (1024 MB). Defined for EL as 'GB'.
049         */
050        public static final long GB = MB * 1024;
051    
052        /**
053         * TeraByte constant (1024 GB). Defined for EL as 'TB'.
054         */
055        public static final long TB = GB * 1024;
056    
057        /**
058         * PetaByte constant (1024 TB). Defined for EL as 'PB'.
059         */
060        public static final long PB = TB * 1024;
061    
062        public static final int SUBMIT_MINUTES = 1;
063        public static final int SUBMIT_HOURS = 60;
064        public static final int SUBMIT_DAYS = 24 * 60;
065    
066        /**
067         * Return the first not <code>null</code> value, or <code>null</code> if both are <code>null</code>. Defined for EL
068         * as 'Object firstNotNull(Object, Object)'.
069         *
070         * @param o1 first value.
071         * @param o2 second value.
072         * @return the first not <code>null</code> value, or or <code>null</code> if both are <code>null</code>
073         */
074        public static Object firstNotNull(Object o1, Object o2) {
075            return (o1 != null) ? o1 : o2;
076        }
077    
078        /**
079         * Return the concatenation of 2 strings. <p/> A string with <code>null</code> value is considered as an empty
080         * string.
081         *
082         * @param s1 first string.
083         * @param s2 second string.
084         * @return the concatenation of <code>s1</code> and <code>s2</code>.
085         */
086        public static String concat(String s1, String s2) {
087            StringBuilder sb = new StringBuilder();
088            if (s1 != null) {
089                sb.append(s1);
090            }
091            if (s2 != null) {
092                sb.append(s2);
093            }
094            return sb.toString();
095        }
096    
097        /**
098         * Replace each occurrence of regular expression match in the first string
099         * with the <code>replacement</code> string. This EL function utilizes the
100         * java String class replaceAll method. For more details please see
101         *
102         * <code>http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll(java.lang.String,%20java.lang.String)</code>
103         *
104         * @param src source string.
105         * @param regex the regular expression to which this string is to be
106         *        matched. null means no replacement.
107         * @param replacement - the string to be substituted for each match. If
108         *        null, it will considered as ""
109         * @return the replaced string.
110         */
111        public static String replaceAll(String src, String regex, String replacement) {
112            if (src != null && regex != null) {
113                if (replacement == null) {
114                    replacement = "";
115                }
116                return src.replaceAll(regex, replacement);
117            }
118            return src;
119        }
120    
121        /**
122         * Add the <code>append</code> string into each splitted sub-strings of the
123         * first string ('src'). The split is performed into <code>src</code> string
124         * using the <code>delimiter</code>. E.g.
125         * <code>appendAll("/a/b/,/c/b/,/c/d/", "ADD", ",")</code> will return
126         * <code>"/a/b/ADD,/c/b/ADD,/c/d/ADD"</code>
127         *
128         * @param src source string.
129         * @param append - the string to be appended for each match. If null, it
130         *        will considered as ""
131         * @param delimeter the string that is used to split the 'src' into
132         *        substring before the append. null means no append.
133         * @return the appended string.
134         */
135        public static String appendAll(String src, String append, String delimeter) {
136            if (src != null && delimeter != null) {
137                if (append == null) {
138                    append = "";
139                }
140                String[] ret = src.split(delimeter);
141                StringBuilder result = new StringBuilder();
142                for (int i = 0; i < ret.length; i++) {
143                    result.append(ret[i]).append(append);
144                    if (i < (ret.length - 1)) { // Don't append to the last item
145                        result.append(delimeter);
146                    }
147                }
148                return result.toString();
149            }
150            return src;
151        }
152    
153        /**
154         *
155         * @param input string to be trimmed
156         * @return the trimmed version of the given string or the empty string if the given string was <code>null</code>
157         */
158        public static String trim(String input) {
159            return (input == null) ? "" : input.trim();
160        }
161    
162        /**
163         * Return the current datetime in ISO8601 using Oozie processing timezone, yyyy-MM-ddTHH:mmZ. i.e.:
164         * 1997-07-16T19:20Z
165         *
166         * @return the formatted time string.
167         */
168        public static String timestamp() {
169            return DateUtils.formatDateOozieTZ(new Date());
170        }
171    
172        /**
173         * Translates a string into <code>application/x-www-form-urlencoded</code> format using UTF-8 encoding scheme. Bytes
174         * for unsafe characters are also obtained using UTF-8 scheme.
175         *
176         * @param input string to be encoded
177         * @return the encoded <code>String</code>
178         */
179        public static String urlEncode(String input) {
180            try {
181                return (input == null) ? "" : URLEncoder.encode(input, "UTF-8");
182            }
183            catch (UnsupportedEncodingException uee) {
184                throw new RuntimeException("It should never happen");
185            }
186        }
187    
188        public static String toJsonStr(Map<String, String> map) {
189            JSONObject json = new JSONObject(map);
190            return XmlUtils.escapeCharsForXML(json.toString());
191        }
192    
193        public static String toPropertiesStr(Map<String, String> map) {
194            Properties props = new Properties();
195            for (Map.Entry<String, String> entry: map.entrySet()) {
196                props.setProperty(entry.getKey(), entry.getValue());
197            }
198            return XmlUtils.escapeCharsForXML(PropertiesUtils.propertiesToString(props));
199        }
200    
201        public static String toConfigurationStr(Map<String, String> map) {
202            Configuration conf = new Configuration(false);
203            for (Map.Entry<String, String> entry: map.entrySet()) {
204                conf.set(entry.getKey(), entry.getValue());
205            }
206            return XmlUtils.escapeCharsForXML(XmlUtils.prettyPrint(conf).toString());
207        }
208    
209    }