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