001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: Locale.java,v 1.7 2009/07/07 17:32:02 bina Exp $ 026 * 027 */ 028 029/* 030 * Portions Copyrighted 2014 ForgeRock AS. 031 * Portions Copyrighted 2014 Nomura Research Institute, Ltd. 032 */ 033package com.sun.identity.shared.locale; 034 035import com.sun.identity.shared.Constants; 036import com.sun.identity.shared.configuration.SystemPropertiesManager; 037import com.sun.identity.shared.debug.Debug; 038import java.io.UnsupportedEncodingException; 039import java.text.MessageFormat; 040import java.text.ParsePosition; 041import java.text.SimpleDateFormat; 042import java.util.BitSet; 043import java.util.Date; 044import java.util.ResourceBundle; 045import java.util.StringTokenizer; 046 047/** 048 * This class <code>Locale.java</code> is a utility that provides 049 * functionality for applications and services to internationalize their 050 * messages. 051 * @supported.all.api 052 */ 053public class Locale { 054 static BitSet dontEncode; 055 056 static final int caseDiff = ('a' - 'A'); 057 058 private static final int LOCALE_STRING_MAX_LEN = 5; 059 060 static java.util.Locale defaultLocale; 061 062 static Debug debug; 063 064 protected static final String USER_PROPERTIES = "amUser"; 065 066 protected static final String DATE_SYNTAX = "dateSyntax"; 067 068 private static final String normalizedDateString = "yyyy/MM/dd HH:mm:ss"; 069 070 private static final SimpleDateFormat normalizedDateFormat; 071 072 private static final String UNDERSCORE = "_"; 073 074 private static final String HYPHEN = "-"; 075 076 077 /* 078 * The list of characters that are not encoded have been determined by 079 * referencing O'Reilly's "HTML: The Definitive Guide" (page 164). 080 */ 081 082 static { 083 // Intialize static variables 084 debug = Debug.getInstance("amUtil"); 085 086 dontEncode = new BitSet(256); 087 int i; 088 for (i = 'a'; i <= 'z'; i++) { 089 dontEncode.set(i); 090 } 091 for (i = 'A'; i <= 'Z'; i++) { 092 dontEncode.set(i); 093 } 094 for (i = '0'; i <= '9'; i++) { 095 dontEncode.set(i); 096 } 097 dontEncode.set(' '); /* 098 * encoding a space to a + is done in the 099 * encode() method 100 */ 101 dontEncode.set('-'); 102 dontEncode.set('_'); 103 dontEncode.set('.'); 104 dontEncode.set('*'); 105 106 String loc = SystemPropertiesManager.get(Constants.AM_LOCALE, "en_US"); 107 defaultLocale = getLocale(loc); 108 normalizedDateFormat = new SimpleDateFormat(normalizedDateString); 109 } 110 111 public static void main(String[] args) { 112 System.out.println(":" + Locale.getLocale(args[0]) + ":"); 113 System.out.println(":" + Locale.getLocale(args[0]).getCountry() + ":"); 114 } 115 116 /** 117 * Gets the locale object for the specified localized string format. 118 * 119 * @param stringformat 120 * String representation of the locale. Examples: 121 * <code>en_US, en_UK, ja_JP</code>. 122 * @return the <code>java.util.locale</code> object. 123 */ 124 public static java.util.Locale getLocale(String stringformat) { 125 java.util.Locale locale = java.util.Locale.getDefault(); 126 if (stringformat == null) { 127 return locale; 128 } 129 130 StringTokenizer tk = null; 131 String lang = ""; 132 String country = ""; 133 String variant = ""; 134 135 if (stringformat.indexOf(HYPHEN) != -1) { 136 tk = new StringTokenizer(stringformat,HYPHEN); 137 } else { 138 tk = new StringTokenizer(stringformat,UNDERSCORE); 139 } 140 141 if (tk != null) { 142 if (tk.hasMoreTokens()) { 143 lang = tk.nextToken(); 144 } 145 if (tk.hasMoreTokens()) { 146 country = tk.nextToken(); 147 } 148 if (tk.hasMoreTokens()) { 149 variant = tk.nextToken(); 150 } 151 locale = new java.util.Locale(lang, country, variant); 152 } 153 154 return locale; 155 } 156 157 /** 158 * Returns locale from accept-language header HTTP accept language header 159 * can have more than one language in the header, we honor the first 160 * language as locale 161 * 162 * @param langstr 163 * Value from Accept-Language header of HTTP 164 * @return locale string in this format <code>en_US, fr</code> 165 */ 166 public static String getLocaleStringFromAcceptLangHeader(String langstr) { 167 168 if (langstr == null) 169 return null; 170 171 char[] lstr = langstr.toCharArray(); 172 int leadSpace = 0; 173 /* 174 * Accept Language Syntax Accept-Language = "Accept-Language" ":" 1#( 175 * language-range [ ";" "q" "=" qvalue ] ) language-range = ( ( 1*8ALPHA 176 * *("-" 1*8ALPHA ) ) | "*" ) For more info Read RFC 2616 Examples: 177 * Accept-Language: da, en-gb;q=0.8, en;q=0.7 Accept-Language: en-gb, en 178 * Accept-Language: ja Accept-Language: zh-cn Accept-Language: * 179 * 180 * We will use first language as locale. We will not process any 181 * further.Netscape,IE will give mostly one language as Accept-Language 182 * header. Max length of string is 5 lang-> 2chars , country -> two 183 * chars and separator is - 184 */ 185 186 try { 187 while (Character.isWhitespace(lstr[leadSpace])) 188 leadSpace++; 189 int len = lstr.length; 190 if (len > leadSpace + LOCALE_STRING_MAX_LEN) 191 len = leadSpace + LOCALE_STRING_MAX_LEN; 192 193 boolean isCountry = false; 194 for (int i = leadSpace; i < len; i++) { 195 char ch = lstr[i]; 196 if (ch == '*') 197 return null; 198 // "*" can be a valid accept-lang but does 199 // give idea about locale, return null and force the caller to 200 // use 201 // default locale 202 if (ch == '-') { 203 lstr[i] = '_'; // We will follow Java mechanism en_US 204 isCountry = true; 205 } else if (ch == ';' || ch == ',') {// Language separators used 206 // by accept-lang 207 return new String(lstr, leadSpace, i - leadSpace); 208 } else if (isCountry) { 209 lstr[i] = Character.toUpperCase(ch); 210 } 211 } 212 return new String(lstr, 0, len); 213 } catch (IndexOutOfBoundsException ex) { 214 return null; 215 } 216 } 217 218 /** 219 * Gets locale from accept-language header HTTP accept language header can 220 * have more than one language in the header, we honor the first language as 221 * locale 222 * 223 * @param langStr 224 * Value from Accept-Language header of HTTP 225 * @return locale string in this format <code>en_US, fr</code>. 226 */ 227 public static java.util.Locale getLocaleObjFromAcceptLangHeader( 228 String langStr) { 229 String lstr = getLocaleStringFromAcceptLangHeader(langStr); 230 231 if (lstr == null) 232 return null; 233 String lang = lstr.substring(0, 2); 234 String country = ""; 235 if (lstr.length() == LOCALE_STRING_MAX_LEN) 236 country = lstr.substring(3, 5); 237 return new java.util.Locale(lang, country); 238 } 239 240 /** 241 * Gets the resource bundle corresponding to the specified locale and the 242 * localized property file name. 243 * 244 * @param bundle 245 * Localized property file name. 246 * @param stringformat 247 * String representation of the locale. 248 * 249 * @return <code>java.util.ResourceBundle</code> object. 250 * 251 */ 252 public static ResourceBundle getResourceBundle(String bundle, 253 String stringformat) { 254 return ResourceBundle.getBundle(bundle, getLocale(stringformat)); 255 } 256 257 protected static ResourceBundle getResourceBundle(String bundle) { 258 return getInstallResourceBundle(bundle); 259 } 260 261 /** 262 * Gets the default install resource bundle for the default locale 263 * 264 * @param bundle 265 * Localized property file name 266 * @return the install resource bundle object 267 */ 268 public static ResourceBundle getInstallResourceBundle(String bundle) { 269 String loc = SystemPropertiesManager.get(Constants.AM_LOCALE, "en_US"); 270 return ResourceBundle.getBundle(bundle, getLocale(loc)); 271 } 272 273 /** 274 * Gets the default locale 275 * 276 * @return the default Locale object 277 */ 278 public static java.util.Locale getDefaultLocale() { 279 return defaultLocale; 280 } 281 282 /** 283 * Formats messages using <code>MessageFormat</code> Class. 284 * 285 * @param formatStr 286 * string format template. 287 * @param obj1 288 * object to be added to the template. 289 * @return formatted message. 290 */ 291 public static String formatMessage(String formatStr, Object obj1) { 292 Object arr[] = new Object[1]; 293 arr[0] = obj1; 294 return MessageFormat.format(formatStr, arr); 295 } 296 297 /** 298 * Formats to format messages using <code>MessageFormat</code> Class. 299 * given params to format them with 300 * 301 * @param formatStr 302 * string format template. 303 * @param objs 304 * objects to be added to the template. 305 * @return formatted message. 306 */ 307 public static String formatMessage(String formatStr, Object[] objs) { 308 return MessageFormat.format(formatStr, objs); 309 } 310 311 /** 312 * Returns the Date object from the date string in <code>ISO-8601</code> 313 * format. OpenSSO stores date in <code>ISO-8601</code> format 314 * <code>yyyy/MM/yy hh:mm</code> 315 * 316 * @param dateString 317 * in the format <code>2002/12/31 23:59</code>. 318 * @return Date object 319 */ 320 public static Date parseNormalizedDateString(String dateString) { 321 if (dateString == null) 322 return null; 323 324 ParsePosition pos = new ParsePosition(0); 325 Date date = normalizedDateFormat.parse(dateString, pos); 326 if (date == null) { 327 debug.error("Locale.parseNormalizedDateString: " 328 + "Unable to parse date string"); 329 } 330 if (debug.messageEnabled()) { 331 debug.message("Locale.parseNormalizedDateString(" + dateString 332 + ")=" + date); 333 } 334 return date; 335 336 } 337 338 /** 339 * Gets Date object from date string with specified locale. 340 * 341 * @param dateString 342 * date string 343 * @param locale 344 * Locale object 345 * @param dateSyntax 346 * syntax of the date string. 347 * 348 * @return Date object returned if <code>dateString</code> matches the 349 * <code> dateSyntax</code>. If the syntax or date string is 350 * empty, or the string does not match the syntax, null will be 351 * returned. 352 */ 353 public static Date parseDateString(String dateString, 354 java.util.Locale locale, String dateSyntax) { 355 if (debug.messageEnabled()) { 356 debug.message("Local.parseDateString(date, locale, syntax)"); 357 debug.message("date string = " + dateString); 358 debug.message("date syntax = " + dateSyntax); 359 debug.message("locale = " + locale.toString()); 360 } 361 if ((dateString == null) || (dateString.length() < 1) 362 || (dateSyntax == null) || (dateSyntax.length() < 1)) { 363 return null; 364 } 365 366 SimpleDateFormat sdf = new SimpleDateFormat(dateSyntax); 367 sdf.setLenient(false); 368 ParsePosition pos = new ParsePosition(0); 369 Date date = sdf.parse(dateString, pos); 370 if (date == null) { 371 debug.warning("Locale.parseDateString: unable to parse the date."); 372 } 373 374 return date; 375 } 376 377 /** 378 * Gets Date object from date string with specified locale. Syntax of date 379 * string is defined in amUser_<locale> properties file. 380 * 381 * @param dateString 382 * date string 383 * @param locale 384 * Locale object 385 * 386 * @return Date object. null will be returned if error happens 387 */ 388 public static Date parseDateString(String dateString, 389 java.util.Locale locale) { 390 ResourceBundle rb = AMResourceBundleCache.getInstance().getResBundle( 391 USER_PROPERTIES, locale); 392 393 if (rb == null) { 394 debug.error("Locale.parseDateString: Unable to get resource " 395 + "bundle. Locale = " + locale); 396 return null; 397 } 398 399 String dateSyntax = null; 400 try { 401 dateSyntax = rb.getString(DATE_SYNTAX); 402 dateSyntax = dateSyntax.trim(); 403 } catch (Exception ex) { 404 debug.error("Locale.parseDateString: Unable to get " + DATE_SYNTAX 405 + ". Locale " + locale); 406 return null; 407 } 408 return parseDateString(dateString, locale, dateSyntax); 409 } 410 411 /** 412 * Converts the Date object into <code>ISO-8601</code> format 413 * <code>yyyy/MM/dd HH:mm</code> like <code>2002/12/23 20:40</code>. 414 * 415 * @param date 416 * to be normalized. 417 * @return date in <code>ISO8601</code> format 418 * <code>2002/12/31 11:59</code>. 419 */ 420 public static String getNormalizedDateString(Date date) { 421 if (date == null) 422 return null; 423 return normalizedDateFormat.format(date); 424 } 425 426 /** 427 * Gets date string from date with specified locale. 428 * 429 * @param date 430 * Date object 431 * @param locale 432 * Locale object 433 * 434 * @return date string. null will be returned if error happens 435 */ 436 public static String getDateString(Date date, java.util.Locale locale) { 437 if (date == null) { 438 return null; 439 } 440 441 ResourceBundle rb = AMResourceBundleCache.getInstance().getResBundle( 442 USER_PROPERTIES, locale); 443 if (rb == null) { 444 debug.error("Locale.getDateString: Unable to get resource " 445 + "bundle. Locale = " + locale); 446 return null; 447 } 448 449 String dateSyntax = null; 450 try { 451 dateSyntax = rb.getString(DATE_SYNTAX); 452 } catch (Exception ex) { 453 debug.error("Locale.getDateString: Unable to get " + DATE_SYNTAX 454 + ". Locale " + locale); 455 return null; 456 } 457 458 if (debug.messageEnabled()) { 459 debug.message("Locale.getDateString: dateSyntax = " + dateSyntax); 460 } 461 462 SimpleDateFormat sdf = new SimpleDateFormat(dateSyntax); 463 return sdf.format(date); 464 } 465 466 /** 467 * Converts date string from source locale to destination locale 468 * 469 * @param srcDateString 470 * source date string 471 * @param srcLocale 472 * source Locale object 473 * @param dstLocale 474 * destination Locale object 475 * 476 * @return converted date string. null will be returned if error happens 477 */ 478 public static String convertDateString(String srcDateString, 479 java.util.Locale srcLocale, java.util.Locale dstLocale) { 480 Date date = parseDateString(srcDateString, srcLocale); 481 482 return getDateString(date, dstLocale); 483 } 484 485 /** 486 * Gets the localized string for the specified key formatted as per passed 487 * parameters. 488 * 489 * @param rb 490 * resource bundle. 491 * @param resource 492 * the specified key. 493 * @param params 494 * formatting done as per these parameters. 495 * 496 * @return the localized string representation formatted as per passed 497 * parameters. 498 */ 499 public static String getString(ResourceBundle rb, String resource, 500 Object[] params) { 501 try { 502 return MessageFormat.format(rb.getString(resource), params); 503 } catch (Exception mre) { 504 if (debug.messageEnabled()) { 505 debug.message("missing resource: " + resource); 506 } 507 } 508 return resource; 509 } 510 511 /** 512 * Gets the localized string for the specified key from the specified 513 * Resource or from the specified default resource formatted as per provided 514 * parameters. 515 * 516 * @param rb 517 * resource bundle. 518 * @param resource 519 * the specified key. 520 * @param defaultRb 521 * Default resource bundle. 522 * @param params 523 * formatting done as per these parameters. 524 * 525 * @return the localized string representation formatted as per passed 526 * parameters. 527 * 528 */ 529 public static String getString(ResourceBundle rb, String resource, 530 ResourceBundle defaultRb, Object[] params) { 531 try { 532 return MessageFormat.format(rb.getString(resource), params); 533 } catch (Exception mre) { 534 try { 535 if (debug.messageEnabled()) { 536 debug.message("missing resource: " + resource); 537 debug.message("fall back to default resource bundle"); 538 } 539 return MessageFormat.format(defaultRb.getString(resource), 540 params); 541 } catch (Exception mrde) { 542 if (debug.messageEnabled()) { 543 debug.message("missing resource in default resource bundle:" 544 + resource); 545 } 546 } 547 } 548 return resource; 549 } 550 551 /** 552 * Gets the localized string for the specified key 553 * 554 * @param rb 555 * resource bundle. 556 * @param resource 557 * the specified key. 558 * @param debug 559 * the debug instance to which the debug messages need to be 560 * printed. 561 * 562 * @return the localized string representation 563 */ 564 public static String getString(ResourceBundle rb, String resource, 565 Debug debug) { 566 try { 567 return rb.getString(resource); 568 } catch (Exception mre) { 569 if (debug.messageEnabled()) { 570 debug.message("missing resource: " + resource); 571 } 572 } 573 return resource; 574 } 575 576 /** 577 * Gets the localized string for the specified key from the specified 578 * Resource or from the specified default resource 579 * 580 * @param rb 581 * resource bundle. 582 * @param resource 583 * the specified key. 584 * @param debug 585 * the debug instance to which the debug messages need to be 586 * printed. 587 * @param defaultRb 588 * Default resource bundle. 589 * 590 * @return the localized string representation 591 */ 592 public static String getString(ResourceBundle rb, String resource, 593 Debug debug, ResourceBundle defaultRb) { 594 try { 595 return rb.getString(resource); 596 } catch (Exception mre) { 597 try { 598 if (debug.messageEnabled()) { 599 debug.message("missing resource: " + resource); 600 debug.message("fall back to default resource bundle"); 601 } 602 return defaultRb.getString(resource); 603 } catch (Exception mrde) { 604 if (debug.messageEnabled()) { 605 debug.message("missing resource in default resource bundle:" 606 + resource); 607 } 608 } 609 } 610 return resource; 611 } 612 613 /** 614 * Gets the localized string for the specified key. 615 * 616 * @param rb 617 * resource bundle. 618 * @param resource 619 * the specified key. 620 * @return the localized string representation 621 */ 622 public static String getString(ResourceBundle rb, String resource) { 623 try { 624 return rb.getString(resource); 625 } catch (Exception mre) { 626 if (debug.messageEnabled()) { 627 debug.message("missing resource: " + resource); 628 } 629 } 630 return resource; 631 } 632 633 /** 634 * Gets the localized string for the specified key from the specified 635 * Resource or from the specified default resource. 636 * 637 * @param rb 638 * resource bundle. 639 * @param resource 640 * the specified key. 641 * @param defaultRb 642 * Default resource bundle. 643 * @return the localized string representation 644 */ 645 public static String getString(ResourceBundle rb, String resource, 646 ResourceBundle defaultRb) { 647 try { 648 return rb.getString(resource); 649 } catch (Exception mre) { 650 try { 651 if (debug.messageEnabled()) { 652 debug.message("missing resource: " + resource); 653 debug.message("fall back to default resource bundle"); 654 } 655 return defaultRb.getString(resource); 656 } catch (Exception mrde) { 657 if (debug.messageEnabled()) { 658 debug.message("missing resource in default resource bundle:" 659 + resource); 660 } 661 } 662 } 663 return resource; 664 } 665 666 /** 667 * This method is replacement function for <code>URLEncoder</code> 668 * Function URL encoder function converts input string into 669 * <code>URLEncoded</code> byte stream after converting Unicode string 670 * into bytes using native encoding. The <code>URLEncoder</code> does not 671 * work for OpenSSO if default encoding is not 672 * <code>UTF-8</code>, hence this method was written. 673 * 674 * @param input 675 * the input string. 676 * @param enc 677 * the encoding format. 678 * @return the encoded string. 679 * @throws UnsupportedEncodingException 680 */ 681 public static String URLEncodeField(String input, String enc) 682 throws UnsupportedEncodingException { 683 int inputLen = input.length(); 684 685 byte[] byteOut = input.getBytes(enc); 686 StringBuffer result = new StringBuffer(inputLen * 4); // approx size 687 for (int i = 0; i < byteOut.length; i++) { 688 int c = byteOut[i] & 0xff; 689 if (dontEncode.get(c)) { 690 if (c == ' ') { 691 c = '+'; 692 } 693 result.append((char) c); 694 } else { 695 result.append('%'); 696 char ch = Character.forDigit((c >> 4) & 0xF, 16); 697 if (('a' <= ch) && (ch <= 'f')) { 698 ch -= caseDiff; 699 } 700 result.append(ch); 701 ch = Character.forDigit(c & 0xF, 16); 702 if (('a' <= ch) && (ch <= 'f')) { 703 ch -= caseDiff; 704 } 705 result.append(ch); 706 } 707 708 } 709 return result.toString(); 710 } 711 712 /** 713 * This method is replacement function for <code>URLEncoder<code> Function 714 * URL encoder function converts input string into <code>URLencoded</code> 715 * byte stream after converting Unicode string into bytes using native 716 * encoding. The <code>URLEncoder</code> does not work for Sun Java System 717 * OpenSSO if default encoding is not <code>UTF-8</code>, hence this 718 * method was written. 719 * 720 * @param input the input string 721 * @param enc the encoding format 722 * @param debug the debug instance to which debug messages need to 723 * be printed 724 * 725 * @return the encoded string 726 */ 727 public static String URLEncodeField(String input, String enc, Debug debug) { 728 int inputLen = input.length(); 729 730 byte[] byteOut; 731 try { 732 byteOut = input.getBytes(enc); 733 } catch (UnsupportedEncodingException ex) { 734 if (debug != null) { 735 debug.error("Locale.URLEncodeField: Unsupported Encoding " 736 + enc, ex); 737 } 738 return input; 739 } 740 741 StringBuffer result = new StringBuffer(inputLen * 4); // approx size 742 for (int i = 0; i < byteOut.length; i++) { 743 int c = byteOut[i] & 0xff; 744 if (dontEncode.get(c)) { 745 if (c == ' ') { 746 c = '+'; 747 } 748 result.append((char) c); 749 } else { 750 result.append('%'); 751 char ch = Character.forDigit((c >> 4) & 0xF, 16); 752 if (('a' <= ch) && (ch <= 'f')) { 753 ch -= caseDiff; 754 } 755 result.append(ch); 756 ch = Character.forDigit(c & 0xF, 16); 757 if (('a' <= ch) && (ch <= 'f')) { 758 ch -= caseDiff; 759 } 760 result.append(ch); 761 } 762 763 } 764 return result.toString(); 765 } 766 767 static public String URLDecodeField(String strIn, Debug debug) { 768 return URLDecodeField(strIn, "UTF-8", debug); 769 } 770 771 /* 772 * Translate the individual field values in the encoding value Do not use 773 * getBytes instead convert unicode into bytes by casting. Using getBytes 774 * results in conversion into platform encoding. It appears to work file in 775 * C locale because default encoding is 8859-1 but fails in japanese locale. 776 * 777 * @param strIn the inputString @param charset character encoding of 778 * inputString @param debug the debug instance to which debug messages need 779 * to be printed. 780 * 781 * @return the decoded string 782 */ 783 static public String URLDecodeField(String strIn, String charset, 784 Debug debug) { 785 786 if (strIn == null) { 787 return strIn; 788 } 789 String strOut = null; 790 try { 791 int len = strIn.length(); 792 byte buf[] = new byte[len]; 793 794 int i = 0; 795 int offset = 0; 796 char[] carr = strIn.toCharArray(); 797 while (i < len) { 798 byte b = (byte) carr[i]; 799 switch (b) { 800 case '%': 801 int val = 0; 802 if (i + 2 < len) { 803 i++; 804 b = (byte) carr[i]; 805 if ('a' <= b && b <= 'f') { 806 b -= caseDiff; 807 } 808 if ('A' <= b && b <= 'F') { 809 val = 10 + b - 'A'; 810 val = val << 4; 811 } else if ('0' <= b && b <= '9') { 812 val = (b - '0') << 4; 813 } else { 814 throw new IllegalArgumentException( 815 "invalid hex char"); 816 } 817 i++; 818 b = (byte) carr[i]; 819 if ('a' <= b && b <= 'f') { 820 b -= caseDiff; 821 } 822 if ('A' <= b && b <= 'F') { 823 val += 10 + b - 'A'; 824 } else if ('0' <= b && b <= '9') { 825 val += b - '0'; 826 } else { 827 throw new IllegalArgumentException( 828 "invalid hex char"); 829 } 830 buf[offset++] = (byte) val; 831 i++; 832 } else { 833 buf[offset++] = (byte) carr[i++]; 834 } 835 break; 836 default: 837 buf[offset++] = (byte) carr[i++]; 838 break; 839 } 840 } 841 if (charset == null || charset.length() == 0) { 842 strOut = new String(buf, 0, offset, "UTF-8"); 843 } else { 844 strOut = new String(buf, 0, offset, charset); 845 } 846 } catch (Exception ex) { 847 debug.error("Locale::decodeField", ex); 848 strOut = strIn; 849 } 850 return strOut; 851 } 852}
Copyright © 2010-2017, ForgeRock All Rights Reserved.