001 /* 002 * Copyright 2004-2005 Stephen J. McConnell. 003 * Copyright 1999-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 014 * implied. 015 * 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 package net.dpml.i18n; 020 021 import java.text.DateFormat; 022 import java.text.MessageFormat; 023 import java.text.ParseException; 024 import java.util.Date; 025 import java.util.Locale; 026 import java.util.MissingResourceException; 027 import java.util.Random; 028 import java.util.ResourceBundle; 029 030 /** 031 * A class to simplify extracting localized strings, icons 032 * and other common resources from a ResourceBundle. 033 * 034 * Reworked to mirror behaviour of StringManager from Tomcat (format() to getString()). 035 * 036 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 037 * @version 1.0.0 038 */ 039 public class Resources 040 { 041 /** 042 * Span width constant. 043 */ 044 private static final int SPAN = 100; 045 046 /** 047 * Random seed. 048 */ 049 private static final Random RANDOM = new Random(); 050 051 /** 052 * Local of Resources 053 */ 054 private final Locale m_locale; 055 056 /** 057 * Resource bundle referenced by manager 058 */ 059 private ResourceBundle m_bundle; 060 061 /** 062 * Base name of resource bundle 063 */ 064 private String m_baseName; 065 066 /** 067 * ClassLoader from which to load resources 068 */ 069 private ClassLoader m_classLoader; 070 071 /** 072 * Constructor that builds a manager in default locale. 073 * 074 * @param baseName the base name of ResourceBundle 075 */ 076 public Resources( final String baseName ) 077 { 078 this( baseName, Locale.getDefault(), null ); 079 } 080 081 /** 082 * Constructor that builds a manager in default locale 083 * using specified ClassLoader. 084 * 085 * @param baseName the base name of ResourceBundle 086 * @param classLoader the classLoader to load ResourceBundle from 087 */ 088 public Resources( final String baseName, final ClassLoader classLoader ) 089 { 090 this( baseName, Locale.getDefault(), classLoader ); 091 } 092 093 /** 094 * Constructor that builds a manager in specified locale. 095 * 096 * @param baseName the base name of ResourceBundle 097 * @param locale the Locale for resource bundle 098 */ 099 public Resources( final String baseName, final Locale locale ) 100 { 101 this( baseName, locale, null ); 102 } 103 104 /** 105 * Constructor that builds a manager in specified locale. 106 * 107 * @param baseName the base name of ResourceBundle 108 * @param locale the Locale for resource bundle 109 * @param classLoader the classLoader to load ResourceBundle from 110 */ 111 public Resources( final String baseName, 112 final Locale locale, 113 final ClassLoader classLoader ) 114 { 115 if( null == baseName ) 116 { 117 throw new NullPointerException( "baseName property is null" ); 118 } 119 if( null == locale ) 120 { 121 throw new NullPointerException( "locale property is null" ); 122 } 123 m_baseName = baseName; 124 m_locale = locale; 125 m_classLoader = classLoader; 126 } 127 128 /** 129 * Retrieve a boolean from bundle. 130 * 131 * @param key the key of resource 132 * @param defaultValue the default value if key is missing 133 * @return the resource boolean 134 * @exception MissingResourceException if the requested key is unknown 135 */ 136 public boolean getBoolean( final String key, final boolean defaultValue ) 137 throws MissingResourceException 138 { 139 try 140 { 141 return getBoolean( key ); 142 } 143 catch( final MissingResourceException mre ) 144 { 145 return defaultValue; 146 } 147 } 148 149 /** 150 * Retrieve a boolean from bundle. 151 * 152 * @param key the key of resource 153 * @return the resource boolean 154 * @exception MissingResourceException if the requested key is unknown 155 */ 156 public boolean getBoolean( final String key ) 157 throws MissingResourceException 158 { 159 final ResourceBundle bundle = getBundle(); 160 final String value = bundle.getString( key ); 161 return value.equalsIgnoreCase( "true" ); 162 } 163 164 /** 165 * Retrieve a byte from bundle. 166 * 167 * @param key the key of resource 168 * @param defaultValue the default value if key is missing 169 * @return the resource byte 170 * @exception MissingResourceException if the requested key is unknown 171 */ 172 public byte getByte( final String key, final byte defaultValue ) 173 throws MissingResourceException 174 { 175 try 176 { 177 return getByte( key ); 178 } 179 catch( final MissingResourceException mre ) 180 { 181 return defaultValue; 182 } 183 } 184 185 /** 186 * Retrieve a byte from bundle. 187 * 188 * @param key the key of resource 189 * @return the resource byte 190 * @exception MissingResourceException if the requested key is unknown 191 */ 192 public byte getByte( final String key ) 193 throws MissingResourceException 194 { 195 final ResourceBundle bundle = getBundle(); 196 final String value = bundle.getString( key ); 197 try 198 { 199 return Byte.parseByte( value ); 200 } 201 catch( final NumberFormatException nfe ) 202 { 203 throw new MissingResourceException( "Expecting a byte value but got " + value, 204 "java.lang.String", 205 key ); 206 } 207 } 208 209 /** 210 * Retrieve a char from bundle. 211 * 212 * @param key the key of resource 213 * @param defaultValue the default value if key is missing 214 * @return the resource char 215 * @exception MissingResourceException if the requested key is unknown 216 */ 217 public char getChar( final String key, final char defaultValue ) 218 throws MissingResourceException 219 { 220 try 221 { 222 return getChar( key ); 223 } 224 catch( final MissingResourceException mre ) 225 { 226 return defaultValue; 227 } 228 } 229 230 /** 231 * Retrieve a char from bundle. 232 * 233 * @param key the key of resource 234 * @return the resource char 235 * @exception MissingResourceException if the requested key is unknown 236 */ 237 public char getChar( final String key ) 238 throws MissingResourceException 239 { 240 final ResourceBundle bundle = getBundle(); 241 final String value = bundle.getString( key ); 242 243 if( 1 == value.length() ) 244 { 245 return value.charAt( 0 ); 246 } 247 else 248 { 249 throw new MissingResourceException( "Expecting a char value but got " + value, 250 "java.lang.String", 251 key ); 252 } 253 } 254 255 /** 256 * Retrieve a short from bundle. 257 * 258 * @param key the key of resource 259 * @param defaultValue the default value if key is missing 260 * @return the resource short 261 * @exception MissingResourceException if the requested key is unknown 262 */ 263 public short getShort( final String key, final short defaultValue ) 264 throws MissingResourceException 265 { 266 try 267 { 268 return getShort( key ); 269 } 270 catch( final MissingResourceException mre ) 271 { 272 return defaultValue; 273 } 274 } 275 276 /** 277 * Retrieve a short from bundle. 278 * 279 * @param key the key of resource 280 * @return the resource short 281 * @exception MissingResourceException if the requested key is unknown 282 */ 283 public short getShort( final String key ) 284 throws MissingResourceException 285 { 286 final ResourceBundle bundle = getBundle(); 287 final String value = bundle.getString( key ); 288 try 289 { 290 return Short.parseShort( value ); 291 } 292 catch( final NumberFormatException nfe ) 293 { 294 throw new MissingResourceException( "Expecting a short value but got " + value, 295 "java.lang.String", 296 key ); 297 } 298 } 299 300 /** 301 * Retrieve a integer from bundle. 302 * 303 * @param key the key of resource 304 * @param defaultValue the default value if key is missing 305 * @return the resource integer 306 * @exception MissingResourceException if the requested key is unknown 307 */ 308 public int getInteger( final String key, final int defaultValue ) 309 throws MissingResourceException 310 { 311 try 312 { 313 return getInteger( key ); 314 } 315 catch( final MissingResourceException mre ) 316 { 317 return defaultValue; 318 } 319 } 320 321 /** 322 * Retrieve a integer from bundle. 323 * 324 * @param key the key of resource 325 * @return the resource integer 326 * @exception MissingResourceException if the requested key is unknown 327 */ 328 public int getInteger( final String key ) 329 throws MissingResourceException 330 { 331 final ResourceBundle bundle = getBundle(); 332 final String value = bundle.getString( key ); 333 try 334 { 335 return Integer.parseInt( value ); 336 } 337 catch( final NumberFormatException nfe ) 338 { 339 throw new MissingResourceException( "Expecting a integer value but got " + value, 340 "java.lang.String", 341 key ); 342 } 343 } 344 345 /** 346 * Retrieve a long from bundle. 347 * 348 * @param key the key of resource 349 * @param defaultValue the default value if key is missing 350 * @return the resource long 351 * @exception MissingResourceException if the requested key is unknown 352 */ 353 public long getLong( final String key, final long defaultValue ) 354 throws MissingResourceException 355 { 356 try 357 { 358 return getLong( key ); 359 } 360 catch( final MissingResourceException mre ) 361 { 362 return defaultValue; 363 } 364 } 365 366 /** 367 * Retrieve a long from bundle. 368 * 369 * @param key the key of resource 370 * @return the resource long 371 * @exception MissingResourceException if the requested key is unknown 372 */ 373 public long getLong( final String key ) 374 throws MissingResourceException 375 { 376 final ResourceBundle bundle = getBundle(); 377 final String value = bundle.getString( key ); 378 try 379 { 380 return Long.parseLong( value ); 381 } 382 catch( final NumberFormatException nfe ) 383 { 384 throw new MissingResourceException( "Expecting a long value but got " + value, 385 "java.lang.String", 386 key ); 387 } 388 } 389 390 /** 391 * Retrieve a float from bundle. 392 * 393 * @param key the key of resource 394 * @param defaultValue the default value if key is missing 395 * @return the resource float 396 * @exception MissingResourceException if the requested key is unknown 397 */ 398 public float getFloat( final String key, final float defaultValue ) 399 throws MissingResourceException 400 { 401 try 402 { 403 return getFloat( key ); 404 } 405 catch( final MissingResourceException mre ) 406 { 407 return defaultValue; 408 } 409 } 410 411 /** 412 * Retrieve a float from bundle. 413 * 414 * @param key the key of resource 415 * @return the resource float 416 * @exception MissingResourceException if the requested key is unknown 417 */ 418 public float getFloat( final String key ) 419 throws MissingResourceException 420 { 421 final ResourceBundle bundle = getBundle(); 422 final String value = bundle.getString( key ); 423 try 424 { 425 return Float.parseFloat( value ); 426 } 427 catch( final NumberFormatException nfe ) 428 { 429 throw new MissingResourceException( "Expecting a float value but got " + value, 430 "java.lang.String", 431 key ); 432 } 433 } 434 435 /** 436 * Retrieve a double from bundle. 437 * 438 * @param key the key of resource 439 * @param defaultValue the default value if key is missing 440 * @return the resource double 441 * @exception MissingResourceException if the requested key is unknown 442 */ 443 public double getDouble( final String key, final double defaultValue ) 444 throws MissingResourceException 445 { 446 try 447 { 448 return getDouble( key ); 449 } 450 catch( final MissingResourceException mre ) 451 { 452 return defaultValue; 453 } 454 } 455 456 /** 457 * Retrieve a double from bundle. 458 * 459 * @param key the key of resource 460 * @return the resource double 461 * @exception MissingResourceException if the requested key is unknown 462 */ 463 public double getDouble( final String key ) 464 throws MissingResourceException 465 { 466 final ResourceBundle bundle = getBundle(); 467 final String value = bundle.getString( key ); 468 try 469 { 470 return Double.parseDouble( value ); 471 } 472 catch( final NumberFormatException nfe ) 473 { 474 throw new MissingResourceException( "Expecting a double value but got " + value, 475 "java.lang.String", 476 key ); 477 } 478 } 479 480 /** 481 * Retrieve a date from bundle. 482 * 483 * @param key the key of resource 484 * @param defaultValue the default value if key is missing 485 * @return the resource date 486 * @exception MissingResourceException if the requested key is unknown 487 */ 488 public Date getDate( final String key, final Date defaultValue ) 489 throws MissingResourceException 490 { 491 try 492 { 493 return getDate( key ); 494 } 495 catch( final MissingResourceException mre ) 496 { 497 return defaultValue; 498 } 499 } 500 501 /** 502 * Retrieve a date from bundle. 503 * 504 * @param key the key of resource 505 * @return the resource date 506 * @exception MissingResourceException if the requested key is unknown 507 */ 508 public Date getDate( final String key ) 509 throws MissingResourceException 510 { 511 final ResourceBundle bundle = getBundle(); 512 final String value = bundle.getString( key ); 513 try 514 { 515 final DateFormat format = 516 DateFormat.getDateInstance( DateFormat.DEFAULT, m_locale ); 517 return format.parse( value ); 518 } 519 catch( final ParseException pe ) 520 { 521 throw new MissingResourceException( "Expecting a date value but got " + value, 522 "java.lang.String", 523 key ); 524 } 525 } 526 527 /** 528 * Retrieve a time from bundle. 529 * 530 * @param key the key of resource 531 * @param defaultValue the default value if key is missing 532 * @return the resource time 533 * @exception MissingResourceException if the requested key is unknown 534 */ 535 public Date getTime( final String key, final Date defaultValue ) 536 throws MissingResourceException 537 { 538 try 539 { 540 return getTime( key ); 541 } 542 catch( final MissingResourceException mre ) 543 { 544 return defaultValue; 545 } 546 } 547 548 /** 549 * Retrieve a time from bundle. 550 * 551 * @param key the key of resource 552 * @return the resource time 553 * @exception MissingResourceException if the requested key is unknown 554 */ 555 public Date getTime( final String key ) 556 throws MissingResourceException 557 { 558 final ResourceBundle bundle = getBundle(); 559 final String value = bundle.getString( key ); 560 try 561 { 562 final DateFormat format = 563 DateFormat.getTimeInstance( DateFormat.DEFAULT, m_locale ); 564 return format.parse( value ); 565 } 566 catch( final ParseException pe ) 567 { 568 throw new MissingResourceException( "Expecting a time value but got " + value, 569 "java.lang.String", 570 key ); 571 } 572 } 573 574 /** 575 * Retrieve a time from bundle. 576 * 577 * @param key the key of resource 578 * @param defaultValue the default value if key is missing 579 * @return the resource time 580 * @exception MissingResourceException if the requested key is unknown 581 */ 582 public Date getDateTime( final String key, final Date defaultValue ) 583 throws MissingResourceException 584 { 585 try 586 { 587 return getDateTime( key ); 588 } 589 catch( final MissingResourceException mre ) 590 { 591 return defaultValue; 592 } 593 } 594 595 /** 596 * Retrieve a date + time from bundle. 597 * 598 * @param key the key of resource 599 * @return the resource date + time 600 * @exception MissingResourceException if the requested key is unknown 601 */ 602 public Date getDateTime( final String key ) 603 throws MissingResourceException 604 { 605 final ResourceBundle bundle = getBundle(); 606 final String value = bundle.getString( key ); 607 try 608 { 609 final DateFormat format = 610 DateFormat.getDateTimeInstance( DateFormat.DEFAULT, DateFormat.DEFAULT, m_locale ); 611 return format.parse( value ); 612 } 613 catch( final ParseException pe ) 614 { 615 throw new MissingResourceException( "Expecting a time value but got " + value, 616 "java.lang.String", 617 key ); 618 } 619 } 620 621 /** 622 * Retrieve a raw string from bundle. 623 * 624 * @param key the key of resource 625 * @return the resource string 626 * @exception MissingResourceException if the requested key is unknown 627 */ 628 public String getString( final String key ) 629 throws MissingResourceException 630 { 631 final ResourceBundle bundle = getBundle(); 632 return bundle.getString( key ); 633 } 634 635 /** 636 * Retrieve a string from resource bundle and format it with specified args. 637 * 638 * @param key the key for resource 639 * @param arg1 an arg 640 * @return the formatted string 641 */ 642 public String getString( final String key, final Object arg1 ) 643 { 644 final Object[] args = new Object[]{arg1}; 645 return format( key, args ); 646 } 647 648 /** 649 * Retrieve a string from resource bundle and format it with specified args. 650 * 651 * @param key the key for resource 652 * @param arg1 an arg 653 * @param arg2 an arg 654 * @return the formatted string 655 */ 656 public String getString( final String key, final Object arg1, final Object arg2 ) 657 { 658 final Object[] args = new Object[]{arg1, arg2}; 659 return format( key, args ); 660 } 661 662 /** 663 * Retrieve a string from resource bundle and format it with specified args. 664 * 665 * @param key the key for resource 666 * @param arg1 an arg 667 * @param arg2 an arg 668 * @param arg3 an arg 669 * @return the formatted string 670 */ 671 public String getString( final String key, 672 final Object arg1, 673 final Object arg2, 674 final Object arg3 ) 675 { 676 final Object[] args = new Object[]{arg1, arg2, arg3}; 677 return format( key, args ); 678 } 679 680 /** 681 * Retrieve a string from resource bundle and format it with specified args. 682 * 683 * @param key the key for resource 684 * @param arg1 an arg 685 * @param arg2 an arg 686 * @param arg3 an arg 687 * @param arg4 an arg 688 * @return the formatted string 689 */ 690 public String getString( final String key, 691 final Object arg1, 692 final Object arg2, 693 final Object arg3, 694 final Object arg4 ) 695 { 696 final Object[] args = new Object[]{arg1, arg2, arg3, arg4}; 697 return format( key, args ); 698 } 699 700 /** 701 * Retrieve a string from resource bundle and format it with specified args. 702 * 703 * @param key the key for resource 704 * @param arg1 an arg 705 * @param arg2 an arg 706 * @param arg3 an arg 707 * @param arg4 an arg 708 * @param arg5 an arg 709 * @return the formatted string 710 */ 711 public String getString( final String key, 712 final Object arg1, 713 final Object arg2, 714 final Object arg3, 715 final Object arg4, 716 final Object arg5 ) 717 { 718 final Object[] args = new Object[]{arg1, arg2, arg3, arg4, arg5}; 719 return format( key, args ); 720 } 721 722 /** 723 * Retrieve a string from resource bundle and format it with specified args. 724 * 725 * @param key the key for resource 726 * @param arg1 an arg 727 * @param arg2 an arg 728 * @param arg3 an arg 729 * @param arg4 an arg 730 * @param arg5 an arg 731 * @param arg6 an arg 732 * @return the formatted string 733 */ 734 public String getString( final String key, 735 final Object arg1, 736 final Object arg2, 737 final Object arg3, 738 final Object arg4, 739 final Object arg5, 740 final Object arg6 ) 741 { 742 final Object[] args = new Object[]{arg1, arg2, arg3, arg4, arg5, arg6}; 743 return format( key, args ); 744 } 745 746 /** 747 * Retrieve a string from resource bundle and format it with specified args. 748 * 749 * @param key the key for resource 750 * @param arg1 an arg 751 * @param arg2 an arg 752 * @param arg3 an arg 753 * @param arg4 an arg 754 * @param arg5 an arg 755 * @param arg6 an arg 756 * @param arg7 an arg 757 * @return the formatted string 758 */ 759 public String getString( final String key, 760 final Object arg1, 761 final Object arg2, 762 final Object arg3, 763 final Object arg4, 764 final Object arg5, 765 final Object arg6, 766 final Object arg7 ) 767 { 768 final Object[] args = new Object[]{arg1, arg2, arg3, arg4, arg5, arg6, arg7}; 769 return format( key, args ); 770 } 771 772 /** 773 * Retrieve a string from resource bundle and format it with specified args. 774 * 775 * @param key the key for resource 776 * @param args an array of args 777 * @return the formatted string 778 */ 779 public String format( final String key, final Object[] args ) 780 { 781 try 782 { 783 final String pattern = getPatternString( key ); 784 StringBuffer buff = new StringBuffer( key.length() + SPAN ); 785 MessageFormat messFormat = new MessageFormat( pattern, m_locale ); 786 messFormat.format( args, buff, null ); 787 String result = buff.toString(); 788 buff.setLength( 0 ); 789 return result; 790 } 791 catch( final MissingResourceException mre ) 792 { 793 final StringBuffer sb = new StringBuffer(); 794 sb.append( "Unknown resource. Bundle: '" ); 795 sb.append( m_baseName ); 796 sb.append( "' Key: '" ); 797 sb.append( key ); 798 sb.append( "' Args: '" ); 799 800 for( int i = 0; i < args.length; i++ ) 801 { 802 if( 0 != i ) 803 { 804 sb.append( "', '" ); 805 } 806 sb.append( args[ i ] ); 807 } 808 809 sb.append( "' Reason: " ); 810 sb.append( mre ); 811 812 return sb.toString(); 813 } 814 } 815 816 /** 817 * Retrieve underlying ResourceBundle. 818 * If bundle has not been loaded it will be loaded by this method. 819 * Access is given in case other resources need to be extracted 820 * that this Manager does not provide simplified access to. 821 * 822 * @return the ResourceBundle 823 * @throws MissingResourceException if an error occurs 824 */ 825 public final ResourceBundle getBundle() 826 throws MissingResourceException 827 { 828 if( null == m_bundle ) 829 { 830 // bundle wasn't cached, so load it, cache it, and return it. 831 ClassLoader classLoader = m_classLoader; 832 if( null == classLoader ) 833 { 834 classLoader = Thread.currentThread().getContextClassLoader(); 835 } 836 if( null != classLoader ) 837 { 838 m_bundle = ResourceBundle.getBundle( m_baseName, m_locale, classLoader ); 839 } 840 else 841 { 842 m_bundle = ResourceBundle.getBundle( m_baseName, m_locale ); 843 } 844 } 845 return m_bundle; 846 } 847 848 /** 849 * Utility method to retrieve a string from ResourceBundle. 850 * If the key is a single string then that will be returned. 851 * If key refers to string array then a random string will be chosen. 852 * Other types cause an exception. 853 * 854 * @param key the key to resource 855 * @return the string resource 856 * @throws MissingResourceException if an error occurs 857 */ 858 private String getPatternString( final String key ) 859 throws MissingResourceException 860 { 861 final ResourceBundle bundle = getBundle(); 862 final Object object = bundle.getObject( key ); 863 864 // is the resource a single string 865 if( object instanceof String ) 866 { 867 return (String) object; 868 } 869 else if( object instanceof String[] ) 870 { 871 //if string array then randomly pick one 872 final String[] strings = (String[]) object; 873 return strings[ RANDOM.nextInt( strings.length ) ]; 874 } 875 else 876 { 877 throw new MissingResourceException( "Unable to find resource of appropriate type.", 878 "java.lang.String", 879 key ); 880 } 881 } 882 }