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 org.apache.hadoop.conf.Configuration;
021import org.jdom.Element;
022import org.json.JSONObject;
023
024import java.text.SimpleDateFormat;
025import java.util.Map;
026import java.util.Properties;
027import java.util.TimeZone;
028import java.util.Date;
029import java.net.URLEncoder;
030import java.io.UnsupportedEncodingException;
031
032/**
033 * Base EL constants and functions.
034 */
035public 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}