1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache license, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the license for the specific language governing permissions and 15 * limitations under the license. 16 */ 17 package org.apache.logging.log4j.util; 18 19 import java.util.Iterator; 20 import java.util.Locale; 21 import java.util.Objects; 22 23 /** 24 * <em>Consider this class private.</em> 25 * 26 * @see <a href="http://commons.apache.org/proper/commons-lang/">Apache Commons Lang</a> 27 */ 28 public final class Strings { 29 30 private static final ThreadLocal<StringBuilder> tempStr = ThreadLocal.withInitial(StringBuilder::new); 31 32 /** 33 * The empty string. 34 */ 35 public static final String EMPTY = ""; 36 37 /** 38 * The empty array. 39 */ 40 public static final String[] EMPTY_ARRAY = {}; 41 42 /** 43 * OS-dependent line separator, defaults to {@code "\n"} if the system property {@code ""line.separator"} cannot be 44 * read. 45 */ 46 public static final String LINE_SEPARATOR = PropertiesUtil.getProperties().getStringProperty("line.separator", 47 "\n"); 48 49 /** 50 * Returns a double quoted string. 51 * 52 * @param str a String 53 * @return {@code "str"} 54 */ 55 public static String dquote(final String str) { 56 return Chars.DQUOTE + str + Chars.DQUOTE; 57 } 58 59 /** 60 * Checks if a String is blank. A blank string is one that is either 61 * {@code null}, empty, or all characters are {@link Character#isWhitespace(char)}. 62 * 63 * @param s the String to check, may be {@code null} 64 * @return {@code true} if the String is {@code null}, empty, or or all characters are {@link Character#isWhitespace(char)} 65 */ 66 public static boolean isBlank(final String s) { 67 if (s == null || s.isEmpty()) { 68 return true; 69 } 70 for (int i = 0; i < s.length(); i++) { 71 char c = s.charAt(i); 72 if (!Character.isWhitespace(c)) { 73 return false; 74 } 75 } 76 return true; 77 } 78 79 /** 80 * <p> 81 * Checks if a CharSequence is empty ("") or null. 82 * </p> 83 * 84 * <pre> 85 * Strings.isEmpty(null) = true 86 * Strings.isEmpty("") = true 87 * Strings.isEmpty(" ") = false 88 * Strings.isEmpty("bob") = false 89 * Strings.isEmpty(" bob ") = false 90 * </pre> 91 * 92 * <p> 93 * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is 94 * available in isBlank(). 95 * </p> 96 * 97 * <p> 98 * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils.isEmpty(CharSequence) 99 * </p> 100 * 101 * @param cs the CharSequence to check, may be null 102 * @return {@code true} if the CharSequence is empty or null 103 */ 104 public static boolean isEmpty(final CharSequence cs) { 105 return cs == null || cs.length() == 0; 106 } 107 108 /** 109 * Checks if a String is not blank. The opposite of {@link #isBlank(String)}. 110 * 111 * @param s the String to check, may be {@code null} 112 * @return {@code true} if the String is non-{@code null} and has content after being trimmed. 113 */ 114 public static boolean isNotBlank(final String s) { 115 return !isBlank(s); 116 } 117 118 /** 119 * <p> 120 * Checks if a CharSequence is not empty ("") and not null. 121 * </p> 122 * 123 * <pre> 124 * Strings.isNotEmpty(null) = false 125 * Strings.isNotEmpty("") = false 126 * Strings.isNotEmpty(" ") = true 127 * Strings.isNotEmpty("bob") = true 128 * Strings.isNotEmpty(" bob ") = true 129 * </pre> 130 * 131 * <p> 132 * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils.isNotEmpty(CharSequence) 133 * </p> 134 * 135 * @param cs the CharSequence to check, may be null 136 * @return {@code true} if the CharSequence is not empty and not null 137 */ 138 public static boolean isNotEmpty(final CharSequence cs) { 139 return !isEmpty(cs); 140 } 141 142 /** 143 * <p>Joins the elements of the provided {@code Iterable} into 144 * a single String containing the provided elements.</p> 145 * 146 * <p>No delimiter is added before or after the list. Null objects or empty 147 * strings within the iteration are represented by empty strings.</p> 148 * 149 * @param iterable the {@code Iterable} providing the values to join together, may be null 150 * @param separator the separator character to use 151 * @return the joined String, {@code null} if null iterator input 152 */ 153 public static String join(final Iterable<?> iterable, final char separator) { 154 if (iterable == null) { 155 return null; 156 } 157 return join(iterable.iterator(), separator); 158 } 159 160 /** 161 * <p>Joins the elements of the provided {@code Iterator} into 162 * a single String containing the provided elements.</p> 163 * 164 * <p>No delimiter is added before or after the list. Null objects or empty 165 * strings within the iteration are represented by empty strings.</p> 166 * 167 * @param iterator the {@code Iterator} of values to join together, may be null 168 * @param separator the separator character to use 169 * @return the joined String, {@code null} if null iterator input 170 */ 171 public static String join(final Iterator<?> iterator, final char separator) { 172 173 // handle null, zero and one elements before building a buffer 174 if (iterator == null) { 175 return null; 176 } 177 if (!iterator.hasNext()) { 178 return EMPTY; 179 } 180 final Object first = iterator.next(); 181 if (!iterator.hasNext()) { 182 return Objects.toString(first, EMPTY); 183 } 184 185 // two or more elements 186 final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small 187 if (first != null) { 188 buf.append(first); 189 } 190 191 while (iterator.hasNext()) { 192 buf.append(separator); 193 final Object obj = iterator.next(); 194 if (obj != null) { 195 buf.append(obj); 196 } 197 } 198 199 return buf.toString(); 200 } 201 202 /** 203 * <p>Gets the leftmost {@code len} characters of a String.</p> 204 * 205 * <p>If {@code len} characters are not available, or the 206 * String is {@code null}, the String will be returned without 207 * an exception. An empty String is returned if len is negative.</p> 208 * 209 * <pre> 210 * StringUtils.left(null, *) = null 211 * StringUtils.left(*, -ve) = "" 212 * StringUtils.left("", *) = "" 213 * StringUtils.left("abc", 0) = "" 214 * StringUtils.left("abc", 2) = "ab" 215 * StringUtils.left("abc", 4) = "abc" 216 * </pre> 217 * 218 * <p> 219 * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils. 220 * </p> 221 * 222 * @param str the String to get the leftmost characters from, may be null 223 * @param len the length of the required String 224 * @return the leftmost characters, {@code null} if null String input 225 */ 226 public static String left(final String str, final int len) { 227 if (str == null) { 228 return null; 229 } 230 if (len < 0) { 231 return EMPTY; 232 } 233 if (str.length() <= len) { 234 return str; 235 } 236 return str.substring(0, len); 237 } 238 239 /** 240 * Returns a quoted string. 241 * 242 * @param str a String 243 * @return {@code 'str'} 244 */ 245 public static String quote(final String str) { 246 return Chars.QUOTE + str + Chars.QUOTE; 247 } 248 249 /** 250 * <p> 251 * Removes control characters (char <= 32) from both ends of this String returning {@code null} if the String is 252 * empty ("") after the trim or if it is {@code null}. 253 * 254 * <p> 255 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. 256 * </p> 257 * 258 * <pre> 259 * Strings.trimToNull(null) = null 260 * Strings.trimToNull("") = null 261 * Strings.trimToNull(" ") = null 262 * Strings.trimToNull("abc") = "abc" 263 * Strings.trimToNull(" abc ") = "abc" 264 * </pre> 265 * 266 * <p> 267 * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils.trimToNull(String) 268 * </p> 269 * 270 * @param str the String to be trimmed, may be null 271 * @return the trimmed String, {@code null} if only chars <= 32, empty or null String input 272 */ 273 public static String trimToNull(final String str) { 274 final String ts = str == null ? null : str.trim(); 275 return isEmpty(ts) ? null : ts; 276 } 277 278 private Strings() { 279 // empty 280 } 281 282 /** 283 * Shorthand for {@code str.toUpperCase(Locale.ROOT);} 284 * @param str The string to upper case. 285 * @return a new string 286 * @see String#toLowerCase(Locale) 287 */ 288 public static String toRootUpperCase(final String str) { 289 return str.toUpperCase(Locale.ROOT); 290 } 291 292 /** 293 * Concatenates 2 Strings without allocation. 294 * @param str1 the first string. 295 * @param str2 the second string. 296 * @return the concatenated String. 297 */ 298 public static String concat(String str1, String str2) { 299 if (isEmpty(str1)) { 300 return str2; 301 } else if (isEmpty(str2)) { 302 return str1; 303 } 304 StringBuilder sb = tempStr.get(); 305 try { 306 return sb.append(str1).append(str2).toString(); 307 } finally { 308 sb.setLength(0); 309 } 310 } 311 312 /** 313 * Creates a new string repeating given {@code str} {@code count} times. 314 * @param str input string 315 * @param count the repetition count 316 * @return the new string 317 * @throws IllegalArgumentException if either {@code str} is null or {@code count} is negative 318 */ 319 public static String repeat(final String str, final int count) { 320 Objects.requireNonNull(str, "str"); 321 if (count < 0) { 322 throw new IllegalArgumentException("count"); 323 } 324 StringBuilder sb = tempStr.get(); 325 try { 326 for (int index = 0; index < count; index++) { 327 sb.append(str); 328 } 329 return sb.toString(); 330 } finally { 331 sb.setLength(0); 332 } 333 } 334 335 }