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