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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.util; 021 022 023import static org.apache.directory.api.util.Chars.isHex; 024import static org.apache.directory.api.util.Hex.encodeHex; 025import static org.apache.directory.api.util.Hex.getHexValue; 026 027import java.io.UnsupportedEncodingException; 028import java.nio.charset.Charset; 029import java.nio.charset.StandardCharsets; 030import java.util.List; 031import java.util.Locale; 032import java.util.Map; 033import java.util.Set; 034import java.util.UUID; 035 036import org.apache.directory.api.i18n.I18n; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040 041/** 042 * Various string manipulation methods that are more efficient then chaining 043 * string operations: all is done in the same buffer without creating a bunch of 044 * string objects. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 */ 048public final class Strings 049{ 050 /** A logger for this class */ 051 private static final Logger LOG = LoggerFactory.getLogger( Strings.class ); 052 053 /** Hex chars */ 054 private static final byte[] HEX_CHAR = new byte[] 055 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 056 057 /** A table containing booleans when the corresponding char is printable */ 058 private static final boolean[] IS_PRINTABLE_CHAR = 059 { 060 // ---, ---, ---, ---, ---, ---, ---, --- 061 false, false, false, false, false, false, false, false, 062 // ---, ---, ---, ---, ---, ---, ---, --- 063 false, false, false, false, false, false, false, false, 064 // ---, ---, ---, ---, ---, ---, ---, --- 065 false, false, false, false, false, false, false, false, 066 // ---, ---, ---, ---, ---, ---, ---, --- 067 false, false, false, false, false, false, false, false, 068 // ' ', ---, ---, ---, ---, ---, ---, "'" 069 true, false, false, false, false, false, false, true, 070 // '(', ')', ---, '+', ',', '-', '.', '/' 071 true, true, false, true, true, true, true, true, 072 // '0', '1', '2', '3', '4', '5', '6', '7', 073 true, true, true, true, true, true, true, true, 074 // '8', '9', ':', ---, ---, '=', ---, '?' 075 true, true, true, false, false, true, false, true, 076 // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 077 false, true, true, true, true, true, true, true, 078 // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' 079 true, true, true, true, true, true, true, true, 080 // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' 081 true, true, true, true, true, true, true, true, 082 // 'X', 'Y', 'Z', ---, ---, ---, ---, --- 083 true, true, true, false, false, false, false, false, 084 // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g' 085 false, true, true, true, true, true, true, true, 086 // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' 087 true, true, true, true, true, true, true, true, 088 // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' 089 true, true, true, true, true, true, true, true, 090 // 'x', 'y', 'z', ---, ---, ---, ---, --- 091 true, true, true, false, false, false, false, false 092 }; 093 094 private static final char[] TO_LOWER_CASE = 095 { 096 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 097 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 098 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 099 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 100 ' ', 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'', 101 '(', ')', 0x2A, '+', ',', '-', '.', '/', 102 '0', '1', '2', '3', '4', '5', '6', '7', 103 '8', '9', ':', 0x3B, 0x3C, '=', 0x3E, '?', 104 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 105 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 106 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 107 'x', 'y', 'z', 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 108 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 109 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 110 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 111 'x', 'y', 'z', 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 112 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 113 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 114 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 115 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 116 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 117 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 118 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 119 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 120 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 121 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 122 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 123 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 124 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 125 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 126 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 127 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 128 }; 129 130 private static final byte[] TO_LOWER_CASE_BYTE = 131 { 132 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 133 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 134 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 135 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 136 ' ', 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'', 137 '(', ')', 0x2A, '+', ',', '-', '.', '/', 138 '0', '1', '2', '3', '4', '5', '6', '7', 139 '8', '9', ':', 0x3B, 0x3C, '=', 0x3E, '?', 140 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 141 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 142 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 143 'x', 'y', 'z', 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 144 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 145 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 146 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 147 'x', 'y', 'z', 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 148 ( byte ) 0x80, ( byte ) 0x81, ( byte ) 0x82, ( byte ) 0x83, 149 ( byte ) 0x84, ( byte ) 0x85, ( byte ) 0x86, ( byte ) 0x87, 150 ( byte ) 0x88, ( byte ) 0x89, ( byte ) 0x8A, ( byte ) 0x8B, 151 ( byte ) 0x8C, ( byte ) 0x8D, ( byte ) 0x8E, ( byte ) 0x8F, 152 ( byte ) 0x90, ( byte ) 0x91, ( byte ) 0x92, ( byte ) 0x93, 153 ( byte ) 0x94, ( byte ) 0x95, ( byte ) 0x96, ( byte ) 0x97, 154 ( byte ) 0x98, ( byte ) 0x99, ( byte ) 0x9A, ( byte ) 0x9B, 155 ( byte ) 0x9C, ( byte ) 0x9D, ( byte ) 0x9E, ( byte ) 0x9F, 156 ( byte ) 0xA0, ( byte ) 0xA1, ( byte ) 0xA2, ( byte ) 0xA3, 157 ( byte ) 0xA4, ( byte ) 0xA5, ( byte ) 0xA6, ( byte ) 0xA7, 158 ( byte ) 0xA8, ( byte ) 0xA9, ( byte ) 0xAA, ( byte ) 0xAB, 159 ( byte ) 0xAC, ( byte ) 0xAD, ( byte ) 0xAE, ( byte ) 0xAF, 160 ( byte ) 0xB0, ( byte ) 0xB1, ( byte ) 0xB2, ( byte ) 0xB3, 161 ( byte ) 0xB4, ( byte ) 0xB5, ( byte ) 0xB6, ( byte ) 0xB7, 162 ( byte ) 0xB8, ( byte ) 0xB9, ( byte ) 0xBA, ( byte ) 0xBB, 163 ( byte ) 0xBC, ( byte ) 0xBD, ( byte ) 0xBE, ( byte ) 0xBF, 164 ( byte ) 0xC0, ( byte ) 0xC1, ( byte ) 0xC2, ( byte ) 0xC3, 165 ( byte ) 0xC4, ( byte ) 0xC5, ( byte ) 0xC6, ( byte ) 0xC7, 166 ( byte ) 0xC8, ( byte ) 0xC9, ( byte ) 0xCA, ( byte ) 0xCB, 167 ( byte ) 0xCC, ( byte ) 0xCD, ( byte ) 0xCE, ( byte ) 0xCF, 168 ( byte ) 0xD0, ( byte ) 0xD1, ( byte ) 0xD2, ( byte ) 0xD3, 169 ( byte ) 0xD4, ( byte ) 0xD5, ( byte ) 0xD6, ( byte ) 0xD7, 170 ( byte ) 0xD8, ( byte ) 0xD9, ( byte ) 0xDA, ( byte ) 0xDB, 171 ( byte ) 0xDC, ( byte ) 0xDD, ( byte ) 0xDE, ( byte ) 0xDF, 172 ( byte ) 0xE0, ( byte ) 0xE1, ( byte ) 0xE2, ( byte ) 0xE3, 173 ( byte ) 0xE4, ( byte ) 0xE5, ( byte ) 0xE6, ( byte ) 0xE7, 174 ( byte ) 0xE8, ( byte ) 0xE9, ( byte ) 0xEA, ( byte ) 0xEB, 175 ( byte ) 0xEC, ( byte ) 0xED, ( byte ) 0xEE, ( byte ) 0xEF, 176 ( byte ) 0xF0, ( byte ) 0xF1, ( byte ) 0xF2, ( byte ) 0xF3, 177 ( byte ) 0xF4, ( byte ) 0xF5, ( byte ) 0xF6, ( byte ) 0xF7, 178 ( byte ) 0xF8, ( byte ) 0xF9, ( byte ) 0xFA, ( byte ) 0xFB, 179 ( byte ) 0xFC, ( byte ) 0xFD, ( byte ) 0xFE, ( byte ) 0xFF 180 }; 181 182 /** upperCase = 'A' .. 'Z', '0'..'9', '-' */ 183 private static final char[] UPPER_CASE = 184 { 185 0, 0, 0, 0, 0, 0, 0, 0, 186 0, 0, 0, 0, 0, 0, 0, 0, 187 0, 0, 0, 0, 0, 0, 0, 0, 188 0, 0, 0, 0, 0, 0, 0, 0, 189 0, 0, 0, 0, 0, 0, 0, 0, 190 0, 0, 0, 0, 0, '-', 0, 0, 191 '0', '1', '2', '3', '4', '5', '6', '7', 192 '8', '9', 0, 0, 0, 0, 0, 0, 193 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 194 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 195 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 196 'X', 'Y', 'Z', 0, 0, 0, 0, 0, 197 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 198 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 199 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 200 'X', 'Y', 'Z', 0, 0, 0, 0, 0, 201 0, 0, 0, 0, 0, 0, 0, 0, 202 0, 0, 0, 0, 0, 0, 0, 0, 203 0, 0, 0, 0, 0, 0, 0, 0, 204 0, 0, 0, 0, 0, 0, 0, 0, 205 0, 0, 0, 0, 0, 0, 0, 0, 206 0, 0, 0, 0, 0, 0, 0, 0, 207 0, 0, 0, 0, 0, 0, 0, 0, 208 0, 0, 0, 0, 0, 0, 0, 0 209 }; 210 211 private static final byte[] UTF8 = new byte[] 212 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 213 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 214 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 215 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 216 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 217 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 218 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 219 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F }; 220 221 /** An empty byte array */ 222 public static final byte[] EMPTY_BYTES = new byte[0]; 223 224 /** An empty String */ 225 public static final String EMPTY_STRING = ""; 226 227 /** An empty String array */ 228 public static final String[] EMPTY_STRING_ARRAY = new String[]{}; 229 230 231 /** 232 * Private constructor 233 */ 234 private Strings() 235 { 236 } 237 238 239 /** 240 * Helper function that dump an array of bytes in hex form 241 * 242 * @param buffer The bytes array to dump 243 * @return A string representation of the array of bytes 244 */ 245 public static String dumpBytes( byte[] buffer ) 246 { 247 if ( buffer == null ) 248 { 249 return ""; 250 } 251 252 StringBuilder sb = new StringBuilder(); 253 254 for ( int i = 0; i < buffer.length; i++ ) 255 { 256 sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ) ).append( 257 ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ) ).append( " " ); 258 } 259 260 return sb.toString(); 261 } 262 263 264 /** 265 * Helper function that dump a byte in hex form 266 * 267 * @param octet The byte to dump 268 * @return A string representation of the byte 269 */ 270 public static String dumpByte( byte octet ) 271 { 272 return Strings.utf8ToString( new byte[] 273 { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } ); 274 } 275 276 277 /** 278 * Helper function that returns a char from an hex 279 * 280 * @param hex The hex to dump 281 * @return A char representation of the hex 282 */ 283 public static char dumpHex( byte hex ) 284 { 285 return ( char ) HEX_CHAR[hex & 0x000F]; 286 } 287 288 289 /** 290 * Helper function that dump an array of bytes in hex pair form, 291 * without '0x' and space chars 292 * 293 * @param buffer The bytes array to dump 294 * @return A string representation of the array of bytes 295 */ 296 public static String dumpHexPairs( byte[] buffer ) 297 { 298 if ( buffer == null ) 299 { 300 return ""; 301 } 302 303 char[] str = new char[buffer.length << 1]; 304 int pos = 0; 305 306 for ( int i = 0; i < buffer.length; i++ ) 307 { 308 str[pos++] = ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ); 309 str[pos++] = ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ); 310 } 311 312 return new String( str ); 313 } 314 315 316 /** 317 * Put common code to deepTrim(String) and deepTrimToLower here. 318 * 319 * @param str the string to deep trim 320 * @param toLowerCase how to normalize for case: upper or lower 321 * @return the deep trimmed string 322 * @see Strings#deepTrim( String ) 323 */ 324 public static String deepTrim( String str, boolean toLowerCase ) 325 { 326 if ( ( null == str ) || ( str.length() == 0 ) ) 327 { 328 return ""; 329 } 330 331 char ch; 332 int length = str.length(); 333 char[] newbuf = new char[length]; 334 boolean wsSeen = false; 335 boolean isStart = true; 336 int pos = 0; 337 338 for ( int i = 0; i < length; i++ ) 339 { 340 ch = str.charAt( i ); 341 342 // filter out all uppercase characters 343 if ( toLowerCase && Character.isUpperCase( ch ) ) 344 { 345 ch = Character.toLowerCase( ch ); 346 } 347 348 // Check to see if we should add space 349 if ( Character.isWhitespace( ch ) ) 350 { 351 // If the buffer has had characters added already check last 352 // added character. Only append a spc if last character was 353 // not whitespace. 354 if ( wsSeen ) 355 { 356 continue; 357 } 358 else 359 { 360 wsSeen = true; 361 362 if ( isStart ) 363 { 364 isStart = false; 365 } 366 else 367 { 368 newbuf[pos++] = ch; 369 } 370 } 371 } 372 else 373 { 374 // Add all non-whitespace 375 wsSeen = false; 376 isStart = false; 377 newbuf[pos++] = ch; 378 } 379 } 380 381 return pos == 0 ? "" : new String( newbuf, 0, wsSeen ? pos - 1 : pos ); 382 } 383 384 385 /** 386 * This does the same thing as a trim but we also lowercase the string while 387 * performing the deep trim within the same buffer. This saves us from 388 * having to create multiple String and StringBuffer objects and is much 389 * more efficient. 390 * 391 * @see Strings#deepTrim( String ) 392 * 393 * @param string The String to modify 394 * @return The modified String 395 */ 396 public static String deepTrimToLower( String string ) 397 { 398 return deepTrim( string, true ); 399 } 400 401 402 /** 403 * A deep trim of a string remove whitespace from the ends as well as 404 * excessive whitespace within the inside of the string between 405 * non-whitespace characters. A deep trim reduces internal whitespace down 406 * to a single space to preserve the whitespace separated tokenization order 407 * of the String. 408 * 409 * @param string the string to deep trim. 410 * @return the trimmed string. 411 */ 412 public static String deepTrim( String string ) 413 { 414 return deepTrim( string, false ); 415 } 416 417 418 /** 419 * Trims several consecutive characters into one. 420 * 421 * @param str the string to trim consecutive characters of 422 * @param ch the character to trim down 423 * @return the newly trimmed down string 424 */ 425 public static String trimConsecutiveToOne( String str, char ch ) 426 { 427 if ( ( null == str ) || ( str.length() == 0 ) ) 428 { 429 return ""; 430 } 431 432 char[] buffer = str.toCharArray(); 433 char[] newbuf = new char[buffer.length]; 434 int pos = 0; 435 boolean same = false; 436 437 for ( int i = 0; i < buffer.length; i++ ) 438 { 439 char car = buffer[i]; 440 441 if ( car == ch ) 442 { 443 if ( same ) 444 { 445 continue; 446 } 447 else 448 { 449 same = true; 450 newbuf[pos++] = car; 451 } 452 } 453 else 454 { 455 same = false; 456 newbuf[pos++] = car; 457 } 458 } 459 460 return new String( newbuf, 0, pos ); 461 } 462 463 464 /** 465 * Truncates large Strings showing a portion of the String's head and tail 466 * with the center cut out and replaced with '...'. Also displays the total 467 * length of the truncated string so size of '...' can be interpreted. 468 * Useful for large strings in UIs or hex dumps to log files. 469 * 470 * @param str the string to truncate 471 * @param head the amount of the head to display 472 * @param tail the amount of the tail to display 473 * @return the center truncated string 474 */ 475 public static String centerTrunc( String str, int head, int tail ) 476 { 477 // Return as-is if String is smaller than or equal to the head plus the 478 // tail plus the number of characters added to the trunc representation 479 // plus the number of digits in the string length. 480 if ( str.length() <= ( head + tail + 7 + str.length() / 10 ) ) 481 { 482 return str; 483 } 484 485 StringBuilder buf = new StringBuilder(); 486 buf.append( '[' ).append( str.length() ).append( "][" ); 487 buf.append( str.substring( 0, head ) ).append( "..." ); 488 buf.append( str.substring( str.length() - tail ) ); 489 buf.append( ']' ); 490 return buf.toString(); 491 } 492 493 494 /** 495 * Gets a hex string from byte array. 496 * 497 * @param res the byte array 498 * @return the hex string representing the binary values in the array 499 */ 500 public static String toHexString( byte[] res ) 501 { 502 StringBuilder buf = new StringBuilder( res.length << 1 ); 503 504 for ( int ii = 0; ii < res.length; ii++ ) 505 { 506 String digit = Integer.toHexString( 0xFF & res[ii] ); 507 508 if ( digit.length() == 1 ) 509 { 510 digit = '0' + digit; 511 } 512 513 buf.append( digit ); 514 } 515 516 return upperCase( buf.toString() ); 517 } 518 519 520 /** 521 * Get byte array from hex string 522 * 523 * @param hexString the hex string to convert to a byte array 524 * @return the byte form of the hex string. 525 */ 526 public static byte[] toByteArray( String hexString ) 527 { 528 int arrLength = hexString.length() >> 1; 529 byte[] buf = new byte[arrLength]; 530 531 for ( int ii = 0; ii < arrLength; ii++ ) 532 { 533 int index = ii << 1; 534 535 String digit = hexString.substring( index, index + 2 ); 536 buf[ii] = ( byte ) Integer.parseInt( digit, 16 ); 537 } 538 539 return buf; 540 } 541 542 543 /** 544 * This method is used to insert HTML block dynamically 545 * 546 * @param source the HTML code to be processes 547 * @param replaceNl if true '\n' will be replaced by <br@gt; 548 * @param replaceTag if true '<' will be replaced by < and '>' will be replaced 549 * by > 550 * @param replaceQuote if true '\"' will be replaced by " 551 * @return the formated html block 552 */ 553 public static String formatHtml( String source, boolean replaceNl, boolean replaceTag, 554 boolean replaceQuote ) 555 { 556 StringBuilder buf = new StringBuilder(); 557 int len = source.length(); 558 559 for ( int i = 0; i < len; i++ ) 560 { 561 char ch = source.charAt( i ); 562 563 switch ( ch ) 564 { 565 case '\"': 566 if ( replaceQuote ) 567 { 568 buf.append( """ ); 569 } 570 else 571 { 572 buf.append( ch ); 573 } 574 break; 575 576 case '<': 577 if ( replaceTag ) 578 { 579 buf.append( "<" ); 580 } 581 else 582 { 583 buf.append( ch ); 584 } 585 break; 586 587 case '>': 588 if ( replaceTag ) 589 { 590 buf.append( ">" ); 591 } 592 else 593 { 594 buf.append( ch ); 595 } 596 break; 597 598 case '\n': 599 if ( replaceNl ) 600 { 601 if ( replaceTag ) 602 { 603 buf.append( "<br>" ); 604 } 605 else 606 { 607 buf.append( "<br>" ); 608 } 609 } 610 else 611 { 612 buf.append( ch ); 613 } 614 break; 615 616 case '\r': 617 break; 618 619 case '&': 620 buf.append( "&" ); 621 break; 622 623 default: 624 buf.append( ch ); 625 break; 626 } 627 } 628 629 return buf.toString(); 630 } 631 632 633 /** 634 * Check if a text is present at the current position in another string. 635 * 636 * @param string The string which contains the data 637 * @param index Current position in the string 638 * @param text The text we want to check 639 * @return <code>true</code> if the string contains the text. 640 */ 641 public static boolean areEquals( String string, int index, String text ) 642 { 643 if ( ( string == null ) || ( text == null ) ) 644 { 645 return false; 646 } 647 648 int length1 = string.length(); 649 int length2 = text.length(); 650 651 if ( ( length1 == 0 ) || ( length1 <= index ) || ( index < 0 ) 652 || ( length2 == 0 ) || ( length2 > ( length1 + index ) ) ) 653 { 654 return false; 655 } 656 else 657 { 658 return string.substring( index ).startsWith( text ); 659 } 660 } 661 662 663 /** 664 * Test if the current character is equal to a specific character. This 665 * function works only for character between 0 and 127, as it does compare a 666 * byte and a char (which is 16 bits wide) 667 * 668 * @param byteArray The buffer which contains the data 669 * @param index Current position in the buffer 670 * @param car The character we want to compare with the current buffer position 671 * @return <code>true</code> if the current character equals the given character. 672 */ 673 public static boolean isCharASCII( byte[] byteArray, int index, char car ) 674 { 675 if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) ) 676 { 677 return false; 678 } 679 else 680 { 681 return ( byteArray[index] == car ) ? true : false; 682 } 683 } 684 685 686 /** 687 * Test if the current character is equal to a specific character. 688 * 689 * @param string The String which contains the data 690 * @param index Current position in the string 691 * @param car The character we want to compare with the current string position 692 * @return <code>true</code> if the current character equals the given character. 693 */ 694 public static boolean isCharASCII( String string, int index, char car ) 695 { 696 if ( string == null ) 697 { 698 return false; 699 } 700 701 int length = string.length(); 702 703 if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) 704 { 705 return false; 706 } 707 else 708 { 709 return string.charAt( index ) == car; 710 } 711 } 712 713 /** 714 * Return an UTF-8 encoded String 715 * 716 * @param bytes The byte array to be transformed to a String 717 * @return A String. 718 */ 719 public static String utf8ToString( byte[] bytes ) 720 { 721 if ( bytes == null ) 722 { 723 return ""; 724 } 725 726 char[] chars = new char[bytes.length]; 727 int pos = 0; 728 729 try 730 { 731 for ( byte b : bytes ) 732 { 733 chars[pos++] = ( char ) UTF8[b]; 734 } 735 } 736 catch ( ArrayIndexOutOfBoundsException aioobe ) 737 { 738 return new String( bytes, StandardCharsets.UTF_8 ); 739 } 740 741 return new String( chars ); 742 } 743 744 745 /** 746 * Return an UTF-8 encoded String 747 * 748 * @param bytes The byte array to be transformed to a String 749 * @param length The length of the byte array to be converted 750 * @return A String. 751 */ 752 public static String utf8ToString( byte[] bytes, int length ) 753 { 754 if ( bytes == null ) 755 { 756 return ""; 757 } 758 759 return new String( bytes, 0, length, StandardCharsets.UTF_8 ); 760 } 761 762 763 /** 764 * Return an UTF-8 encoded String 765 * 766 * @param bytes The byte array to be transformed to a String 767 * @param start the starting position in the byte array 768 * @param length The length of the byte array to be converted 769 * @return A String. 770 */ 771 public static String utf8ToString( byte[] bytes, int start, int length ) 772 { 773 if ( bytes == null ) 774 { 775 return ""; 776 } 777 778 return new String( bytes, start, length, StandardCharsets.UTF_8 ); 779 } 780 781 782 /** 783 * Check if a text is present at the current position in a buffer. 784 * 785 * @param bytes The buffer which contains the data 786 * @param index Current position in the buffer 787 * @param text The text we want to check 788 * @return <code>true</code> if the buffer contains the text. 789 */ 790 public static int areEquals( byte[] bytes, int index, String text ) 791 { 792 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 ) 793 || ( text == null ) ) 794 { 795 return StringConstants.NOT_EQUAL; 796 } 797 else 798 { 799 byte[] data = text.getBytes( StandardCharsets.UTF_8 ); 800 801 return areEquals( bytes, index, data ); 802 } 803 } 804 805 806 /** 807 * Check if a text is present at the current position in a buffer. 808 * 809 * @param chars The buffer which contains the data 810 * @param index Current position in the buffer 811 * @param text The text we want to check 812 * @return <code>true</code> if the buffer contains the text. 813 */ 814 public static int areEquals( char[] chars, int index, String text ) 815 { 816 return areEquals( chars, index, text, true ); 817 } 818 819 820 /** 821 * Check if a text is present at the current position in a buffer. 822 * 823 * @param chars The buffer which contains the data 824 * @param index Current position in the buffer 825 * @param text The text we want to check 826 * @param caseSensitive If the comparison is case-sensitive 827 * @return <code>true</code> if the buffer contains the text. 828 */ 829 public static int areEquals( char[] chars, int index, String text, boolean caseSensitive ) 830 { 831 if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 ) 832 || ( text == null ) ) 833 { 834 return StringConstants.NOT_EQUAL; 835 } 836 else 837 { 838 char[] data = text.toCharArray(); 839 840 return areEquals( chars, index, data, caseSensitive ); 841 } 842 } 843 844 845 /** 846 * Check if a text is present at the current position in a buffer. 847 * 848 * @param chars The buffer which contains the data 849 * @param index Current position in the buffer 850 * @param chars2 The text we want to check 851 * @return <code>true</code> if the buffer contains the text. 852 */ 853 public static int areEquals( char[] chars, int index, char[] chars2 ) 854 { 855 return areEquals( chars, index, chars2, true ); 856 } 857 858 859 /** 860 * Check if a text is present at the current position in a buffer. 861 * 862 * @param chars The buffer which contains the data 863 * @param index Current position in the buffer 864 * @param chars2 The text we want to check 865 * @param caseSensitive If the comparison is case-sensitive 866 * @return <code>true</code> if the buffer contains the text. 867 */ 868 public static int areEquals( char[] chars, int index, char[] chars2, boolean caseSensitive ) 869 { 870 if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 ) 871 || ( chars2 == null ) || ( chars2.length == 0 ) 872 || ( chars2.length > ( chars.length - index ) ) ) 873 { 874 return StringConstants.NOT_EQUAL; 875 } 876 else 877 { 878 for ( int i = 0; i < chars2.length; i++ ) 879 { 880 char c1 = chars[index++]; 881 char c2 = chars2[i]; 882 883 if ( !caseSensitive ) 884 { 885 c1 = Character.toLowerCase( c1 ); 886 c2 = Character.toLowerCase( c2 ); 887 } 888 889 if ( c1 != c2 ) 890 { 891 return StringConstants.NOT_EQUAL; 892 } 893 } 894 895 return index; 896 } 897 } 898 899 900 /** 901 * Check if a text is present at the current position in a buffer. 902 * 903 * @param bytes The buffer which contains the data 904 * @param index Current position in the buffer 905 * @param bytes2 The text we want to check 906 * @return <code>true</code> if the buffer contains the text. 907 */ 908 public static int areEquals( byte[] bytes, int index, byte[] bytes2 ) 909 { 910 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 ) 911 || ( bytes2 == null ) || ( bytes2.length == 0 ) 912 || ( bytes2.length > ( bytes.length - index ) ) ) 913 { 914 return StringConstants.NOT_EQUAL; 915 } 916 else 917 { 918 for ( int i = 0; i < bytes2.length; i++ ) 919 { 920 if ( bytes[index++] != bytes2[i] ) 921 { 922 return StringConstants.NOT_EQUAL; 923 } 924 } 925 926 return index; 927 } 928 } 929 930 931 /** 932 * <p> 933 * Checks if a String is empty ("") or null. 934 * </p> 935 * 936 * <pre> 937 * StringUtils.isEmpty(null) = true 938 * StringUtils.isEmpty("") = true 939 * StringUtils.isEmpty(" ") = false 940 * StringUtils.isEmpty("bob") = false 941 * StringUtils.isEmpty(" bob ") = false 942 * </pre> 943 * 944 * <p> 945 * NOTE: This method changed in Lang version 2.0. It no longer trims the 946 * String. That functionality is available in isBlank(). 947 * </p> 948 * 949 * @param str the String to check, may be null 950 * @return <code>true</code> if the String is empty or null 951 */ 952 public static boolean isEmpty( String str ) 953 { 954 return ( str == null ) || ( str.length() == 0 ); 955 } 956 957 958 /** 959 * Checks if a bytes array is empty or null. 960 * 961 * @param bytes The bytes array to check, may be null 962 * @return <code>true</code> if the bytes array is empty or null 963 */ 964 public static boolean isEmpty( byte[] bytes ) 965 { 966 return ( bytes == null ) || ( bytes.length == 0 ); 967 } 968 969 970 /** 971 * <p> 972 * Removes spaces (char <= 32) from both start and ends of this String, 973 * handling <code>null</code> by returning <code>null</code>. 974 * </p> 975 * Trim removes start and end characters <= 32. 976 * 977 * <pre> 978 * StringUtils.trim(null) = null 979 * StringUtils.trim("") = "" 980 * StringUtils.trim(" ") = "" 981 * StringUtils.trim("abc") = "abc" 982 * StringUtils.trim(" abc ") = "abc" 983 * </pre> 984 * 985 * @param str the String to be trimmed, may be null 986 * @return the trimmed string, <code>null</code> if null String input 987 */ 988 public static String trim( String str ) 989 { 990 return isEmpty( str ) ? "" : str.trim(); 991 } 992 993 994 /** 995 * <p> 996 * Removes spaces (char <= 32) from both start and ends of this bytes 997 * array, handling <code>null</code> by returning <code>null</code>. 998 * </p> 999 * Trim removes start and end characters <= 32. 1000 * 1001 * <pre> 1002 * StringUtils.trim(null) = null 1003 * StringUtils.trim("") = "" 1004 * StringUtils.trim(" ") = "" 1005 * StringUtils.trim("abc") = "abc" 1006 * StringUtils.trim(" abc ") = "abc" 1007 * </pre> 1008 * 1009 * @param bytes the byte array to be trimmed, may be null 1010 * 1011 * @return the trimmed byte array 1012 */ 1013 public static byte[] trim( byte[] bytes ) 1014 { 1015 if ( isEmpty( bytes ) ) 1016 { 1017 return EMPTY_BYTES; 1018 } 1019 1020 int start = trimLeft( bytes, 0 ); 1021 int end = trimRight( bytes, bytes.length - 1 ); 1022 1023 int length = end - start + 1; 1024 1025 if ( length != 0 ) 1026 { 1027 byte[] newBytes = new byte[end - start + 1]; 1028 1029 System.arraycopy( bytes, start, newBytes, 0, length ); 1030 1031 return newBytes; 1032 } 1033 else 1034 { 1035 return EMPTY_BYTES; 1036 } 1037 } 1038 1039 1040 /** 1041 * <p> 1042 * Removes spaces (char <= 32) from start of this String, handling 1043 * <code>null</code> by returning <code>null</code>. 1044 * </p> 1045 * Trim removes start characters <= 32. 1046 * 1047 * <pre> 1048 * StringUtils.trimLeft(null) = null 1049 * StringUtils.trimLeft("") = "" 1050 * StringUtils.trimLeft(" ") = "" 1051 * StringUtils.trimLeft("abc") = "abc" 1052 * StringUtils.trimLeft(" abc ") = "abc " 1053 * </pre> 1054 * 1055 * @param str the String to be trimmed, may be null 1056 * @return the trimmed string, <code>null</code> if null String input 1057 */ 1058 public static String trimLeft( String str ) 1059 { 1060 if ( isEmpty( str ) ) 1061 { 1062 return ""; 1063 } 1064 1065 int start = 0; 1066 int end = str.length(); 1067 1068 while ( ( start < end ) && ( str.charAt( start ) == ' ' ) ) 1069 { 1070 start++; 1071 } 1072 1073 return start == 0 ? str : str.substring( start ); 1074 } 1075 1076 1077 /** 1078 * <p> 1079 * Removes spaces (char <= 32) from start of this array, handling 1080 * <code>null</code> by returning <code>null</code>. 1081 * </p> 1082 * Trim removes start characters <= 32. 1083 * 1084 * <pre> 1085 * StringUtils.trimLeft(null) = null 1086 * StringUtils.trimLeft("") = "" 1087 * StringUtils.trimLeft(" ") = "" 1088 * StringUtils.trimLeft("abc") = "abc" 1089 * StringUtils.trimLeft(" abc ") = "abc " 1090 * </pre> 1091 * 1092 * @param chars the chars array to be trimmed, may be null 1093 * @param pos The position in the char[] 1094 * @return the position of the first char which is not a space, or the last 1095 * position of the array. 1096 */ 1097 public static int trimLeft( char[] chars, int pos ) 1098 { 1099 if ( chars == null ) 1100 { 1101 return pos; 1102 } 1103 1104 while ( ( pos < chars.length ) && ( chars[pos] == ' ' ) ) 1105 { 1106 pos++; 1107 } 1108 1109 return pos; 1110 } 1111 1112 1113 /** 1114 * <p> 1115 * Removes spaces (char <= 32) from a position in this array, handling 1116 * <code>null</code> by returning <code>null</code>. 1117 * </p> 1118 * Trim removes start characters <= 32. 1119 * 1120 * <pre> 1121 * StringUtils.trimLeft(null) = null 1122 * StringUtils.trimLeft("",...) = "" 1123 * StringUtils.trimLeft(" ",...) = "" 1124 * StringUtils.trimLeft("abc",...) = "abc" 1125 * StringUtils.trimLeft(" abc ",...) = "abc " 1126 * </pre> 1127 * 1128 * @param string the string to be trimmed, may be null 1129 * @param pos The starting position 1130 */ 1131 public static void trimLeft( String string, Position pos ) 1132 { 1133 if ( string == null ) 1134 { 1135 return; 1136 } 1137 1138 int length = string.length(); 1139 1140 while ( ( pos.start < length ) && ( string.charAt( pos.start ) == ' ' ) ) 1141 { 1142 pos.start++; 1143 } 1144 1145 pos.end = pos.start; 1146 } 1147 1148 1149 /** 1150 * <p> 1151 * Removes spaces (char <= 32) from a position in this array, handling 1152 * <code>null</code> by returning <code>null</code>. 1153 * </p> 1154 * Trim removes start characters <= 32. 1155 * 1156 * <pre> 1157 * StringUtils.trimLeft(null) = null 1158 * StringUtils.trimLeft("",...) = "" 1159 * StringUtils.trimLeft(" ",...) = "" 1160 * StringUtils.trimLeft("abc",...) = "abc" 1161 * StringUtils.trimLeft(" abc ",...) = "abc " 1162 * </pre> 1163 * 1164 * @param bytes the byte array to be trimmed, may be null 1165 * @param pos The starting position 1166 */ 1167 public static void trimLeft( byte[] bytes, Position pos ) 1168 { 1169 if ( bytes == null ) 1170 { 1171 return; 1172 } 1173 1174 int length = bytes.length; 1175 1176 while ( ( pos.start < length ) && ( bytes[pos.start] == ' ' ) ) 1177 { 1178 pos.start++; 1179 } 1180 1181 pos.end = pos.start; 1182 } 1183 1184 1185 /** 1186 * <p> 1187 * Removes spaces (char <= 32) from start of this array, handling 1188 * <code>null</code> by returning <code>null</code>. 1189 * </p> 1190 * Trim removes start characters <= 32. 1191 * 1192 * <pre> 1193 * StringUtils.trimLeft(null) = null 1194 * StringUtils.trimLeft("") = "" 1195 * StringUtils.trimLeft(" ") = "" 1196 * StringUtils.trimLeft("abc") = "abc" 1197 * StringUtils.trimLeft(" abc ") = "abc " 1198 * </pre> 1199 * 1200 * @param bytes the byte array to be trimmed, may be null 1201 * @param pos The position in the byte[] 1202 * @return the position of the first byte which is not a space, or the last 1203 * position of the array. 1204 */ 1205 public static int trimLeft( byte[] bytes, int pos ) 1206 { 1207 if ( bytes == null ) 1208 { 1209 return pos; 1210 } 1211 1212 while ( ( pos < bytes.length ) && ( bytes[pos] == ' ' ) ) 1213 { 1214 pos++; 1215 } 1216 1217 return pos; 1218 } 1219 1220 1221 /** 1222 * <p> 1223 * Removes spaces (char <= 32) from end of this String, handling 1224 * <code>null</code> by returning <code>null</code>. 1225 * </p> 1226 * Trim removes start characters <= 32. 1227 * 1228 * <pre> 1229 * StringUtils.trimRight(null) = null 1230 * StringUtils.trimRight("") = "" 1231 * StringUtils.trimRight(" ") = "" 1232 * StringUtils.trimRight("abc") = "abc" 1233 * StringUtils.trimRight(" abc ") = " abc" 1234 * </pre> 1235 * 1236 * @param str the String to be trimmed, may be null 1237 * @return the trimmed string, <code>null</code> if null String input 1238 */ 1239 public static String trimRight( String str ) 1240 { 1241 if ( isEmpty( str ) ) 1242 { 1243 return ""; 1244 } 1245 1246 int length = str.length(); 1247 int end = length; 1248 1249 while ( ( end > 0 ) && ( str.charAt( end - 1 ) == ' ' ) ) 1250 { 1251 if ( ( end > 1 ) && ( str.charAt( end - 2 ) == '\\' ) ) 1252 { 1253 break; 1254 } 1255 1256 end--; 1257 } 1258 1259 return end == length ? str : str.substring( 0, end ); 1260 } 1261 1262 1263 /** 1264 * <p> 1265 * Removes spaces (char <= 32) from end of this String, handling 1266 * <code>null</code> by returning <code>null</code>. 1267 * </p> 1268 * Trim removes start characters <= 32. 1269 * 1270 * <pre> 1271 * StringUtils.trimRight(null) = null 1272 * StringUtils.trimRight("") = "" 1273 * StringUtils.trimRight(" ") = "" 1274 * StringUtils.trimRight("abc") = "abc" 1275 * StringUtils.trimRight(" abc ") = " abc" 1276 * </pre> 1277 * 1278 * @param str the String to be trimmed, may be null 1279 * @param escapedSpace The last escaped space, if any 1280 * @return the trimmed string, <code>null</code> if null String input 1281 */ 1282 public static String trimRight( String str, int escapedSpace ) 1283 { 1284 if ( isEmpty( str ) ) 1285 { 1286 return ""; 1287 } 1288 1289 int length = str.length(); 1290 int end = length; 1291 1292 while ( ( end > 0 ) && ( str.charAt( end - 1 ) == ' ' ) && ( end > escapedSpace ) ) 1293 { 1294 if ( ( end > 1 ) && ( str.charAt( end - 2 ) == '\\' ) ) 1295 { 1296 break; 1297 } 1298 1299 end--; 1300 } 1301 1302 return end == length ? str : str.substring( 0, end ); 1303 } 1304 1305 1306 /** 1307 * <p> 1308 * Removes spaces (char <= 32) from end of this array, handling 1309 * <code>null</code> by returning <code>null</code>. 1310 * </p> 1311 * Trim removes start characters <= 32. 1312 * 1313 * <pre> 1314 * StringUtils.trimRight(null) = null 1315 * StringUtils.trimRight("") = "" 1316 * StringUtils.trimRight(" ") = "" 1317 * StringUtils.trimRight("abc") = "abc" 1318 * StringUtils.trimRight(" abc ") = " abc" 1319 * </pre> 1320 * 1321 * @param chars the chars array to be trimmed, may be null 1322 * @param pos The position in the char[] 1323 * @return the position of the first char which is not a space, or the last 1324 * position of the array. 1325 */ 1326 public static int trimRight( char[] chars, int pos ) 1327 { 1328 if ( chars == null ) 1329 { 1330 return pos; 1331 } 1332 1333 while ( ( pos >= 0 ) && ( chars[pos - 1] == ' ' ) ) 1334 { 1335 pos--; 1336 } 1337 1338 return pos; 1339 } 1340 1341 1342 /** 1343 * <p> 1344 * Removes spaces (char <= 32) from end of this string, handling 1345 * <code>null</code> by returning <code>null</code>. 1346 * </p> 1347 * Trim removes start characters <= 32. 1348 * 1349 * <pre> 1350 * StringUtils.trimRight(null) = null 1351 * StringUtils.trimRight("") = "" 1352 * StringUtils.trimRight(" ") = "" 1353 * StringUtils.trimRight("abc") = "abc" 1354 * StringUtils.trimRight(" abc ") = " abc" 1355 * </pre> 1356 * 1357 * @param string the string to be trimmed, may be null 1358 * @param pos The position in the String 1359 * @return the position of the first char which is not a space, or the last 1360 * position of the string. 1361 */ 1362 public static String trimRight( String string, Position pos ) 1363 { 1364 if ( string == null ) 1365 { 1366 return ""; 1367 } 1368 1369 while ( ( pos.end >= 0 ) && ( string.charAt( pos.end - 1 ) == ' ' ) ) 1370 { 1371 if ( ( pos.end > 1 ) && ( string.charAt( pos.end - 2 ) == '\\' ) ) 1372 { 1373 break; 1374 } 1375 1376 pos.end--; 1377 } 1378 1379 return pos.end == string.length() ? string : string.substring( 0, pos.end ); 1380 } 1381 1382 1383 /** 1384 * <p> 1385 * Removes spaces (char <= 32) from end of this string, handling 1386 * <code>null</code> by returning <code>null</code>. 1387 * </p> 1388 * Trim removes start characters <= 32. 1389 * 1390 * <pre> 1391 * StringUtils.trimRight(null) = null 1392 * StringUtils.trimRight("") = "" 1393 * StringUtils.trimRight(" ") = "" 1394 * StringUtils.trimRight("abc") = "abc" 1395 * StringUtils.trimRight(" abc ") = " abc" 1396 * </pre> 1397 * 1398 * @param bytes the byte array to be trimmed, may be null 1399 * @param pos The position in the byte[] 1400 * @return the position of the first char which is not a space, or the last 1401 * position of the byte array. 1402 */ 1403 public static String trimRight( byte[] bytes, Position pos ) 1404 { 1405 if ( bytes == null ) 1406 { 1407 return ""; 1408 } 1409 1410 while ( ( pos.end >= 0 ) && ( bytes[pos.end - 1] == ' ' ) ) 1411 { 1412 if ( ( pos.end > 1 ) && ( bytes[pos.end - 2] == '\\' ) ) 1413 { 1414 break; 1415 } 1416 1417 pos.end--; 1418 } 1419 1420 if ( pos.end == bytes.length ) 1421 { 1422 return utf8ToString( bytes ); 1423 } 1424 else 1425 { 1426 return utf8ToString( bytes, pos.end ); 1427 } 1428 } 1429 1430 1431 /** 1432 * <p> 1433 * Removes spaces (char <= 32) from end of this array, handling 1434 * <code>null</code> by returning <code>null</code>. 1435 * </p> 1436 * Trim removes start characters <= 32. 1437 * 1438 * <pre> 1439 * StringUtils.trimRight(null) = null 1440 * StringUtils.trimRight("") = "" 1441 * StringUtils.trimRight(" ") = "" 1442 * StringUtils.trimRight("abc") = "abc" 1443 * StringUtils.trimRight(" abc ") = " abc" 1444 * </pre> 1445 * 1446 * @param bytes the byte array to be trimmed, may be null 1447 * @param pos The position in the byte[] 1448 * @return the position of the first char which is not a space, or the last 1449 * position of the array. 1450 */ 1451 public static int trimRight( byte[] bytes, int pos ) 1452 { 1453 if ( bytes == null ) 1454 { 1455 return pos; 1456 } 1457 1458 while ( ( pos >= 0 ) && ( bytes[pos] == ' ' ) ) 1459 { 1460 pos--; 1461 } 1462 1463 return pos; 1464 } 1465 1466 1467 /** 1468 * Get the character at a given position in a string, checking for limits 1469 * 1470 * @param string The string which contains the data 1471 * @param index Current position in the string 1472 * @return The character at the given position, or '\0' if something went wrong 1473 */ 1474 public static char charAt( String string, int index ) 1475 { 1476 if ( string == null ) 1477 { 1478 return '\0'; 1479 } 1480 1481 int length = string.length(); 1482 1483 if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) 1484 { 1485 return '\0'; 1486 } 1487 else 1488 { 1489 return string.charAt( index ); 1490 } 1491 } 1492 1493 1494 /** 1495 * Get the byte at a given position in a byte array, checking for limits 1496 * 1497 * @param bytes The byte[] which contains the data 1498 * @param index Current position in the byte[] 1499 * @return The byte at the given position, or '\0' if something went wrong 1500 */ 1501 public static byte byteAt( byte[] bytes, int index ) 1502 { 1503 if ( bytes == null ) 1504 { 1505 return '\0'; 1506 } 1507 1508 int length = bytes.length; 1509 1510 if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) 1511 { 1512 return '\0'; 1513 } 1514 else 1515 { 1516 return bytes[index]; 1517 } 1518 } 1519 1520 1521 /** 1522 * Get the char at a given position in a byte array, checking for limits 1523 * 1524 * @param chars The char[] which contains the data 1525 * @param index Current position in the char[] 1526 * @return The byte at the given position, or '\0' if something went wrong 1527 */ 1528 public static char charAt( char[] chars, int index ) 1529 { 1530 if ( chars == null ) 1531 { 1532 return '\0'; 1533 } 1534 1535 int length = chars.length; 1536 1537 if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) 1538 { 1539 return '\0'; 1540 } 1541 else 1542 { 1543 return chars[index]; 1544 } 1545 } 1546 1547 1548 /** 1549 * Transform an array of ASCII bytes to a string. the byte array should contains 1550 * only values in [0, 127]. 1551 * 1552 * @param bytes The byte array to transform 1553 * @return The resulting string 1554 */ 1555 public static String asciiBytesToString( byte[] bytes ) 1556 { 1557 if ( ( bytes == null ) || ( bytes.length == 0 ) ) 1558 { 1559 return ""; 1560 } 1561 1562 char[] result = new char[bytes.length]; 1563 1564 for ( int i = 0; i < bytes.length; i++ ) 1565 { 1566 result[i] = ( char ) bytes[i]; 1567 } 1568 1569 return new String( result ); 1570 } 1571 1572 1573 /** 1574 * Return UTF-8 encoded byte[] representation of a String 1575 * 1576 * @param string The string to be transformed to a byte array 1577 * @return The transformed byte array 1578 */ 1579 public static byte[] getBytesUtf8( String string ) 1580 { 1581 if ( string == null ) 1582 { 1583 return EMPTY_BYTES; 1584 } 1585 1586 return string.getBytes( StandardCharsets.UTF_8 ); 1587 } 1588 1589 1590 /** 1591 * When the string to convert to bytes is pure ascii, this is a faster 1592 * method than the getBytesUtf8. Otherwise, it's slower. 1593 * 1594 * @param string The string to convert to byte[] 1595 * @return The bytes 1596 */ 1597 public static byte[] getBytesUtf8Ascii( String string ) 1598 { 1599 if ( string == null ) 1600 { 1601 return EMPTY_BYTES; 1602 } 1603 1604 try 1605 { 1606 char[] chars = string.toCharArray(); 1607 byte[] bytes = new byte[chars.length]; 1608 int pos = 0; 1609 1610 for ( char c : chars ) 1611 { 1612 bytes[pos++] = UTF8[c]; 1613 } 1614 1615 return bytes; 1616 } 1617 catch ( ArrayIndexOutOfBoundsException aioobe ) 1618 { 1619 return string.getBytes( StandardCharsets.UTF_8 ); 1620 } 1621 } 1622 1623 1624 /** 1625 * Get the default charset 1626 * 1627 * @return The default charset 1628 */ 1629 public static String getDefaultCharsetName() 1630 { 1631 return Charset.defaultCharset().name(); 1632 } 1633 1634 1635 /** 1636 * <p> 1637 * Compares two Strings, returning <code>true</code> if they are equal. 1638 * </p> 1639 * <p> 1640 * <code>null</code>s are handled without exceptions. Two 1641 * <code>null</code> references are considered to be equal. The comparison 1642 * is case sensitive. 1643 * </p> 1644 * 1645 * <pre> 1646 * StringUtils.equals(null, null) = true 1647 * StringUtils.equals(null, "abc") = false 1648 * StringUtils.equals("abc", null) = false 1649 * StringUtils.equals("abc", "abc") = true 1650 * StringUtils.equals("abc", "ABC") = false 1651 * </pre> 1652 * 1653 * @see String#equals(Object) 1654 * @param str1 the first String, may be null 1655 * @param str2 the second String, may be null 1656 * @return <code>true</code> if the Strings are equal, case sensitive, or 1657 * both <code>null</code> 1658 */ 1659 public static boolean equals( String str1, String str2 ) 1660 { 1661 return str1 == null ? str2 == null : str1.equals( str2 ); 1662 } 1663 1664 1665 /** 1666 * Utility method that return a String representation of a list 1667 * 1668 * @param list The list to transform to a string 1669 * @return A csv string 1670 */ 1671 public static String listToString( List<?> list ) 1672 { 1673 if ( ( list == null ) || list.isEmpty() ) 1674 { 1675 return ""; 1676 } 1677 1678 StringBuilder sb = new StringBuilder(); 1679 boolean isFirst = true; 1680 1681 for ( Object elem : list ) 1682 { 1683 if ( isFirst ) 1684 { 1685 isFirst = false; 1686 } 1687 else 1688 { 1689 sb.append( ", " ); 1690 } 1691 1692 sb.append( elem ); 1693 } 1694 1695 return sb.toString(); 1696 } 1697 1698 1699 /** 1700 * Utility method that return a String representation of a set 1701 * 1702 * @param set The set to transform to a string 1703 * @return A csv string 1704 */ 1705 public static String setToString( Set<?> set ) 1706 { 1707 if ( ( set == null ) || set.isEmpty() ) 1708 { 1709 return ""; 1710 } 1711 1712 StringBuilder sb = new StringBuilder(); 1713 boolean isFirst = true; 1714 1715 for ( Object elem : set ) 1716 { 1717 if ( isFirst ) 1718 { 1719 isFirst = false; 1720 } 1721 else 1722 { 1723 sb.append( ", " ); 1724 } 1725 1726 sb.append( elem ); 1727 } 1728 1729 return sb.toString(); 1730 } 1731 1732 1733 /** 1734 * Utility method that return a String representation of a list 1735 * 1736 * @param list The list to transform to a string 1737 * @param tabs The tabs to add in front of the elements 1738 * @return A csv string 1739 */ 1740 public static String listToString( List<?> list, String tabs ) 1741 { 1742 if ( ( list == null ) || list.isEmpty() ) 1743 { 1744 return ""; 1745 } 1746 1747 StringBuilder sb = new StringBuilder(); 1748 1749 for ( Object elem : list ) 1750 { 1751 sb.append( tabs ); 1752 sb.append( elem ); 1753 sb.append( '\n' ); 1754 } 1755 1756 return sb.toString(); 1757 } 1758 1759 1760 /** 1761 * Utility method that return a String representation of a map. The elements 1762 * will be represented as "key = value" 1763 * 1764 * @param map The map to transform to a string 1765 * @return A csv string 1766 */ 1767 public static String mapToString( Map<?, ?> map ) 1768 { 1769 if ( ( map == null ) || map.isEmpty() ) 1770 { 1771 return ""; 1772 } 1773 1774 StringBuilder sb = new StringBuilder(); 1775 boolean isFirst = true; 1776 1777 for ( Map.Entry<?, ?> entry : map.entrySet() ) 1778 { 1779 if ( isFirst ) 1780 { 1781 isFirst = false; 1782 } 1783 else 1784 { 1785 sb.append( ", " ); 1786 } 1787 1788 sb.append( entry.getKey() ); 1789 sb.append( " = '" ).append( entry.getValue() ).append( "'" ); 1790 } 1791 1792 return sb.toString(); 1793 } 1794 1795 1796 /** 1797 * Utility method that return a String representation of a map. The elements 1798 * will be represented as "key = value" 1799 * 1800 * @param map The map to transform to a string 1801 * @param tabs The tabs to add in ffront of the elements 1802 * @return A csv string 1803 */ 1804 public static String mapToString( Map<?, ?> map, String tabs ) 1805 { 1806 if ( ( map == null ) || map.isEmpty() ) 1807 { 1808 return ""; 1809 } 1810 1811 StringBuilder sb = new StringBuilder(); 1812 1813 for ( Map.Entry<?, ?> entry : map.entrySet() ) 1814 { 1815 sb.append( tabs ); 1816 sb.append( entry.getKey() ); 1817 1818 sb.append( " = '" ).append( entry.getValue().toString() ).append( "'\n" ); 1819 } 1820 1821 return sb.toString(); 1822 } 1823 1824 1825 /** 1826 * Rewrote the toLowercase method to improve performances. 1827 * In Ldap, attributesType are supposed to use ASCII chars : 1828 * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. 1829 * 1830 * @param value The String to lowercase 1831 * @return The lowercase string 1832 * @deprecated Use {@link #toLowerCaseAscii(String)} 1833 */ 1834 @Deprecated 1835 public static String toLowerCase( String value ) 1836 { 1837 if ( ( null == value ) || ( value.length() == 0 ) ) 1838 { 1839 return ""; 1840 } 1841 1842 char[] chars = value.toCharArray(); 1843 1844 for ( int i = 0; i < chars.length; i++ ) 1845 { 1846 chars[i] = TO_LOWER_CASE[chars[i]]; 1847 } 1848 1849 return new String( chars ); 1850 } 1851 1852 1853 /** 1854 * Rewrote the toLowercase method to improve performances. 1855 * In Ldap, attributesType are supposed to use ASCII chars : 1856 * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. 1857 * 1858 * @param value The String to lowercase 1859 * @return The lowercase string 1860 */ 1861 public static String toLowerCaseAscii( String value ) 1862 { 1863 if ( ( null == value ) || ( value.length() == 0 ) ) 1864 { 1865 return ""; 1866 } 1867 1868 char[] chars = value.toCharArray(); 1869 1870 for ( int i = 0; i < chars.length; i++ ) 1871 { 1872 chars[i] = TO_LOWER_CASE[chars[i]]; 1873 } 1874 1875 return new String( chars ); 1876 } 1877 1878 1879 /** 1880 * Rewrote the toLowercase method to improve performances. 1881 * In Ldap, attributesType are supposed to use ASCII chars : 1882 * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. 1883 * 1884 * @param value The byte[] to lowercase 1885 * @return The lowercase string 1886 */ 1887 public static String toLowerCase( byte[] value ) 1888 { 1889 if ( ( null == value ) || ( value.length == 0 ) ) 1890 { 1891 return ""; 1892 } 1893 1894 for ( int i = 0; i < value.length; i++ ) 1895 { 1896 value[i] = TO_LOWER_CASE_BYTE[value[i]]; 1897 } 1898 1899 return Strings.utf8ToString( value ); 1900 } 1901 1902 1903 /** 1904 * Rewrote the toLowercase method to improve performances. 1905 * In Ldap, attributesType are supposed to use ASCII chars : 1906 * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. 1907 * 1908 * @param value The String to uppercase 1909 * @return The uppercase string 1910 * @deprecated Use {@link #toUpperCaseAscii(String)} 1911 */ 1912 @Deprecated 1913 public static String toUpperCase( String value ) 1914 { 1915 if ( ( null == value ) || ( value.length() == 0 ) ) 1916 { 1917 return ""; 1918 } 1919 1920 char[] chars = value.toCharArray(); 1921 1922 for ( int i = 0; i < chars.length; i++ ) 1923 { 1924 chars[i] = UPPER_CASE[chars[i]]; 1925 } 1926 1927 return new String( chars ); 1928 } 1929 1930 1931 /** 1932 * Rewrote the toLowercase method to improve performances. 1933 * In Ldap, attributesType are supposed to use ASCII chars : 1934 * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. 1935 * 1936 * @param value The String to uppercase 1937 * @return The uppercase string 1938 */ 1939 public static String toUpperCaseAscii( String value ) 1940 { 1941 if ( ( null == value ) || ( value.length() == 0 ) ) 1942 { 1943 return ""; 1944 } 1945 1946 char[] chars = value.toCharArray(); 1947 1948 for ( int i = 0; i < chars.length; i++ ) 1949 { 1950 chars[i] = UPPER_CASE[chars[i]]; 1951 } 1952 1953 return new String( chars ); 1954 } 1955 1956 1957 /** 1958 * <p> 1959 * Converts a String to upper case as per {@link String#toUpperCase( Locale )}. 1960 * </p> 1961 * <p> 1962 * A <code>null</code> input String returns <code>null</code>. 1963 * </p> 1964 * 1965 * <pre> 1966 * StringUtils.upperCase(null) = null 1967 * StringUtils.upperCase("") = "" 1968 * StringUtils.upperCase("aBc") = "ABC" 1969 * </pre> 1970 * 1971 * @param str the String to upper case, may be null 1972 * @return the upper cased String, <code>null</code> if null String input 1973 */ 1974 public static String upperCase( String str ) 1975 { 1976 if ( str == null ) 1977 { 1978 return null; 1979 } 1980 1981 return str.toUpperCase( Locale.ROOT ); 1982 } 1983 1984 1985 /** 1986 * <p> 1987 * Converts a String to lower case as per {@link String#toLowerCase()}. 1988 * </p> 1989 * <p> 1990 * A <code>null</code> input String returns <code>null</code>. 1991 * </p> 1992 * 1993 * <pre> 1994 * StringUtils.lowerCase(null) = null 1995 * StringUtils.lowerCase("") = "" 1996 * StringUtils.lowerCase("aBc") = "abc" 1997 * </pre> 1998 * 1999 * @param str the String to lower case, may be null 2000 * @return the lower cased String, <code>null</code> if null String input 2001 */ 2002 public static String lowerCase( String str ) 2003 { 2004 if ( str == null ) 2005 { 2006 return null; 2007 } 2008 2009 return str.toLowerCase( Locale.ROOT ); 2010 } 2011 2012 2013 /** 2014 * Rewrote the toLowercase method to improve performances. 2015 * In Ldap, attributesType are supposed to use ASCII chars : 2016 * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. We will take 2017 * care of any other chars either. 2018 * 2019 * @param str The String to lowercase 2020 * @return The lowercase string 2021 */ 2022 public static String lowerCaseAscii( String str ) 2023 { 2024 if ( str == null ) 2025 { 2026 return null; 2027 } 2028 2029 char[] chars = str.toCharArray(); 2030 int pos = 0; 2031 2032 for ( char c : chars ) 2033 { 2034 chars[pos++] = TO_LOWER_CASE[c]; 2035 } 2036 2037 return new String( chars ); 2038 } 2039 2040 2041 /** 2042 * 2043 * Check that a String is a valid PrintableString. A PrintableString contains only 2044 * the following set of chars : 2045 * { ' ', ''', '(', ')', '+', '-', '.', '/', [0-9], ':', '=', '?', [A-Z], [a-z]} 2046 * 2047 * @param str The String to check 2048 * @return <code>true</code> if the string is a PrintableString or is empty, 2049 * <code>false</code> otherwise 2050 */ 2051 public static boolean isPrintableString( String str ) 2052 { 2053 if ( ( str == null ) || ( str.length() == 0 ) ) 2054 { 2055 return true; 2056 } 2057 2058 for ( char c : str.toCharArray() ) 2059 { 2060 if ( ( c > 127 ) || !IS_PRINTABLE_CHAR[c] ) 2061 { 2062 return false; 2063 } 2064 } 2065 2066 return true; 2067 } 2068 2069 2070 /** 2071 * <p> 2072 * Checks if a String is not empty ("") and not null. 2073 * </p> 2074 * 2075 * <pre> 2076 * StringUtils.isNotEmpty(null) = false 2077 * StringUtils.isNotEmpty("") = false 2078 * StringUtils.isNotEmpty(" ") = true 2079 * StringUtils.isNotEmpty("bob") = true 2080 * StringUtils.isNotEmpty(" bob ") = true 2081 * </pre> 2082 * 2083 * @param str the String to check, may be null 2084 * @return <code>true</code> if the String is not empty and not null 2085 */ 2086 public static boolean isNotEmpty( String str ) 2087 { 2088 return ( str != null ) && ( str.length() > 0 ); 2089 } 2090 2091 2092 /** 2093 * 2094 * Check that a String is a valid IA5String. An IA5String contains only 2095 * char which values is between [0, 7F] 2096 * 2097 * @param str The String to check 2098 * @return <code>true</code> if the string is an IA5String or is empty, 2099 * <code>false</code> otherwise 2100 */ 2101 public static boolean isIA5String( String str ) 2102 { 2103 if ( ( str == null ) || ( str.length() == 0 ) ) 2104 { 2105 return true; 2106 } 2107 2108 // All the chars must be in [0x00, 0x7F] 2109 for ( char c : str.toCharArray() ) 2110 { 2111 if ( ( c < 0 ) || ( c > 0x7F ) ) 2112 { 2113 return false; 2114 } 2115 } 2116 2117 return true; 2118 } 2119 2120 2121 /** 2122 * Checks to see if a String is a valid UUID. 2123 * 2124 * @param uuid the UUID to check for validity 2125 * @return true if the UUID is valid, false otherwise 2126 */ 2127 public static boolean isValidUuid( String uuid ) 2128 { 2129 if ( uuid.length() < 36 ) 2130 { 2131 return false; 2132 } 2133 2134 if ( isHex( uuid.charAt( 0 ) ) && isHex( uuid.charAt( 1 ) ) && isHex( uuid.charAt( 2 ) ) 2135 && isHex( uuid.charAt( 3 ) ) && isHex( uuid.charAt( 4 ) ) && isHex( uuid.charAt( 5 ) ) 2136 && isHex( uuid.charAt( 6 ) ) && isHex( uuid.charAt( 7 ) ) && ( uuid.charAt( 8 ) == '-' ) 2137 && isHex( uuid.charAt( 9 ) ) && isHex( uuid.charAt( 10 ) ) && isHex( uuid.charAt( 11 ) ) 2138 && isHex( uuid.charAt( 12 ) ) && ( uuid.charAt( 13 ) == '-' ) && isHex( uuid.charAt( 14 ) ) 2139 && isHex( uuid.charAt( 15 ) ) && isHex( uuid.charAt( 16 ) ) && isHex( uuid.charAt( 17 ) ) 2140 && ( uuid.charAt( 18 ) == '-' ) && isHex( uuid.charAt( 19 ) ) && isHex( uuid.charAt( 20 ) ) 2141 && isHex( uuid.charAt( 21 ) ) && isHex( uuid.charAt( 22 ) ) && ( uuid.charAt( 23 ) == '-' ) 2142 && isHex( uuid.charAt( 24 ) ) && isHex( uuid.charAt( 25 ) ) && isHex( uuid.charAt( 26 ) ) 2143 && isHex( uuid.charAt( 27 ) ) && isHex( uuid.charAt( 28 ) ) && isHex( uuid.charAt( 29 ) ) 2144 && isHex( uuid.charAt( 30 ) ) && isHex( uuid.charAt( 31 ) ) && isHex( uuid.charAt( 32 ) ) 2145 && isHex( uuid.charAt( 33 ) ) && isHex( uuid.charAt( 34 ) ) && isHex( uuid.charAt( 35 ) ) ) 2146 { 2147 // There is not that much more we can check. 2148 LOG.debug( "Syntax valid for '{}'", uuid ); 2149 return true; 2150 } 2151 2152 LOG.debug( "Syntax invalid for '{}'", uuid ); 2153 return false; 2154 } 2155 2156 2157 /** 2158 * converts the bytes of a UUID to string 2159 * 2160 * @param bytes bytes of a UUID 2161 * @return UUID in string format 2162 */ 2163 public static String uuidToString( byte[] bytes ) 2164 { 2165 if ( ( bytes == null ) || ( bytes.length != 16 ) ) 2166 { 2167 return "Invalid UUID"; 2168 } 2169 2170 char[] hex = encodeHex( bytes ); 2171 StringBuilder sb = new StringBuilder(); 2172 sb.append( hex, 0, 8 ); 2173 sb.append( '-' ); 2174 sb.append( hex, 8, 4 ); 2175 sb.append( '-' ); 2176 sb.append( hex, 12, 4 ); 2177 sb.append( '-' ); 2178 sb.append( hex, 16, 4 ); 2179 sb.append( '-' ); 2180 sb.append( hex, 20, 12 ); 2181 2182 return Strings.toLowerCaseAscii( sb.toString() ); 2183 } 2184 2185 2186 /** 2187 * converts the string representation of an UUID to bytes 2188 * 2189 * @param string the string representation of an UUID 2190 * @return the bytes, null if the the syntax is not valid 2191 */ 2192 public static byte[] uuidToBytes( String string ) 2193 { 2194 if ( !isValidUuid( string ) ) 2195 { 2196 return null; 2197 } 2198 2199 char[] chars = string.toCharArray(); 2200 byte[] bytes = new byte[16]; 2201 bytes[0] = getHexValue( chars[0], chars[1] ); 2202 bytes[1] = getHexValue( chars[2], chars[3] ); 2203 bytes[2] = getHexValue( chars[4], chars[5] ); 2204 bytes[3] = getHexValue( chars[6], chars[7] ); 2205 2206 bytes[4] = getHexValue( chars[9], chars[10] ); 2207 bytes[5] = getHexValue( chars[11], chars[12] ); 2208 2209 bytes[6] = getHexValue( chars[14], chars[15] ); 2210 bytes[7] = getHexValue( chars[16], chars[17] ); 2211 2212 bytes[8] = getHexValue( chars[19], chars[20] ); 2213 bytes[9] = getHexValue( chars[21], chars[22] ); 2214 2215 bytes[10] = getHexValue( chars[24], chars[25] ); 2216 bytes[11] = getHexValue( chars[26], chars[27] ); 2217 bytes[12] = getHexValue( chars[28], chars[29] ); 2218 bytes[13] = getHexValue( chars[30], chars[31] ); 2219 bytes[14] = getHexValue( chars[32], chars[33] ); 2220 bytes[15] = getHexValue( chars[34], chars[35] ); 2221 2222 return bytes; 2223 } 2224 2225 2226 /** 2227 * Copy a byte array into a new byte array 2228 * 2229 * @param value the byte array to copy 2230 * @return The copied byte array 2231 */ 2232 public static byte[] copy( byte[] value ) 2233 { 2234 if ( isEmpty( value ) ) 2235 { 2236 return EMPTY_BYTES; 2237 } 2238 2239 byte[] copy = new byte[value.length]; 2240 System.arraycopy( value, 0, copy, 0, value.length ); 2241 2242 return copy; 2243 } 2244 2245 2246 /** 2247 * From commons-httpclients. Converts the byte array of HTTP content 2248 * characters to a string. If the specified charset is not supported, 2249 * default system encoding is used. 2250 * 2251 * @param data the byte array to be encoded 2252 * @param offset the index of the first byte to encode 2253 * @param length the number of bytes to encode 2254 * @param charset the desired character encoding 2255 * @return The result of the conversion. 2256 * @since 3.0 2257 */ 2258 public static String getString( final byte[] data, int offset, int length, String charset ) 2259 { 2260 if ( data == null ) 2261 { 2262 throw new IllegalArgumentException( I18n.err( I18n.ERR_04411 ) ); 2263 } 2264 2265 if ( ( charset == null ) || ( charset.length() == 0 ) ) 2266 { 2267 throw new IllegalArgumentException( I18n.err( I18n.ERR_04412 ) ); 2268 } 2269 2270 try 2271 { 2272 return new String( data, offset, length, charset ); 2273 } 2274 catch ( UnsupportedEncodingException e ) 2275 { 2276 return new String( data, offset, length, Charset.defaultCharset() ); 2277 } 2278 } 2279 2280 2281 /** 2282 * From commons-httpclients. Converts the byte array of HTTP content 2283 * characters to a string. If the specified charset is not supported, 2284 * default system encoding is used. 2285 * 2286 * @param data the byte array to be encoded 2287 * @param charset the desired character encoding 2288 * @return The result of the conversion. 2289 * @since 3.0 2290 */ 2291 public static String getString( final byte[] data, String charset ) 2292 { 2293 return getString( data, 0, data.length, charset ); 2294 } 2295 2296 2297 /** 2298 * Create a new UUID using a long as the least significant bits 2299 * 2300 * @param value The least significant bits. 2301 * @return The created UUID 2302 */ 2303 public static String getUUID( long value ) 2304 { 2305 return new UUID( 0, value ).toString(); 2306 } 2307 2308 2309 /** 2310 * Past an ASCII String to a number 2311 * 2312 * @param value The string to parse 2313 * @return the parsed value. 2314 */ 2315 public static int parseInt( String value ) 2316 { 2317 long res = 0; 2318 2319 for ( char c : value.toCharArray() ) 2320 { 2321 if ( ( c >= '0' ) && ( c <= '9' ) ) 2322 { 2323 res = res * 10 + ( c - '0' ); 2324 2325 if ( res > Integer.MAX_VALUE ) 2326 { 2327 throw new NumberFormatException( "Integer " + value + " is too big" ); 2328 } 2329 } 2330 else 2331 { 2332 throw new NumberFormatException( "Integer " + value + " is not valid" ); 2333 } 2334 } 2335 2336 return ( int ) res; 2337 } 2338}