1 /* 2 * Copyright (c) 2005, 2006 Imola Informatica. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the LGPL License v2.1 5 * which accompanies this distribution, and is available at 6 * http://www.gnu.org/licenses/lgpl.html 7 */ 8 9 10 package it.imolinfo.jbi4cics.jbi; 11 12 import java.text.MessageFormat; 13 import java.util.Locale; 14 import java.util.MissingResourceException; 15 import java.util.ResourceBundle; 16 17 /** 18 * Class dedicated to the internationalization of application messages. 19 * <br> 20 * 21 * @author <a href="mailto:mcimatti@imolinfo.it">Marco Cimatti</a> 22 */ 23 public final class Messages { 24 /* 25 * DON'T ADD LOGGING TO THIS CLASS, because this class is used by logging 26 * itself, so it will cause java.lang.StackOverflowError while initializing 27 * the logging system 28 */ 29 30 /** 31 * The bundle name for a class. 32 */ 33 private static final String BUNDLE_NAME = "messages.Bundle"; 34 35 /** 36 * The suffix added to the package name of a class to identify the correct 37 * resource bundle to be used by the class itself. 38 */ 39 private static final String BUNDLE_NAME_SUFFIX = "." + BUNDLE_NAME; 40 41 /** 42 * The resource bundle containing all localized strings. 43 */ 44 private final ResourceBundle bundle; 45 46 /** 47 * Retrieves the <code>ResourceBundle</code> used by this instance. 48 * 49 * @param clazz the class used to identify the resource bundle. Must not 50 * be <code>null</code>. 51 * @param locale the locale to use. Must not be <code>null</code>. 52 */ 53 private Messages(final Class clazz, final Locale locale) { 54 bundle = ResourceBundle.getBundle(getBundleName(clazz), locale, 55 clazz.getClassLoader()); 56 } 57 58 /** 59 * Factory method to create a <code>Messages</code> object from a 60 * <code>Class</code>. 61 * 62 * @param clazz the class used to find the resource bundle. Must not be 63 * <code>null</code>. 64 * @return a <code>Messages</code> object related to <code>clazz</code>, 65 * never <code>null</code>. The messages bundle used is related to 66 * the default locale. 67 */ 68 public static Messages getMessages(final Class clazz) { 69 return new Messages(clazz, Locale.getDefault()); 70 } 71 72 /** 73 * Factory method to create a <code>Messages</code> object from a 74 * <code>Class</code> and a <code>Locale</code>. 75 * 76 * @param clazz the class used to find the resource bundle. Must not be 77 * <code>null</code>. 78 * @param locale the <code>Locale</code> to find the correct resource 79 * bundle. If <code>null</code>, the default locale will be 80 * used. 81 * @return a <code>Messages</code> object related to <code>clazz</code> and 82 * <code>locale</code>, never <code>null</code>. <code>ResourceBundle</code>. 83 */ 84 public static Messages getMessages(final Class clazz, final Locale locale) { 85 if (locale == null) { 86 return new Messages(clazz, Locale.getDefault()); 87 } 88 return new Messages(clazz, locale); 89 } 90 91 /** 92 * Retrieves a localized <code>String</code> which may contains parameters. 93 * This method applies a <code>MessageFormat</code> to the value with the 94 * arguments provided. 95 * 96 * @param key the resource key to retrieve the (localized) message. 97 * @param args the optional <code>MessageFormat</code> arguments. 98 * @return the localized messaged related to the key <code>key</code> after 99 * the substitution of its parameters with values 100 * <code>args</code>. 101 */ 102 public String getString(final String key, final Object ... args) { 103 String rawValue; 104 105 try { 106 synchronized (bundle) { 107 rawValue = bundle.getString(key); 108 } 109 } catch (MissingResourceException e) { 110 return key; 111 } 112 try { 113 return MessageFormat.format(rawValue, args); 114 } catch (IllegalArgumentException e) { 115 return rawValue; 116 } 117 } 118 119 /** 120 * Determines the bundle name for a <code>Class</code>. 121 * 122 * @param clazz the <code>Class</code> object used to find the 123 * <code>ResourceBundle</code>. Must not be 124 * <code>null</code>. 125 * @return the name of the <code>ResourceBundle</code> related to 126 * <code>clazz</code>, ever different from <code>null</code>. 127 */ 128 private static String getBundleName(final Class clazz) { 129 String packageName = getPackageName(clazz); 130 131 if (packageName.length() == 0) { 132 return BUNDLE_NAME; 133 } 134 return packageName.concat(BUNDLE_NAME_SUFFIX); 135 } 136 137 /** 138 * Retrieves the package name for a <code>Class</code> object. 139 * If the class doesn't have a package, the empty string is returned. 140 * 141 * @param clazz the class to retrieve its package name. Must not be 142 * <code>null</code>. 143 * @return the package name for <code>clazz</code> if it exists, otherwise 144 * the empty string. 145 */ 146 private static String getPackageName(final Class clazz) { 147 Package pack = clazz.getPackage(); 148 String className; 149 int lastDotIndex; 150 151 if (pack != null) { 152 return pack.getName(); 153 } 154 155 if (clazz.isArray()) { 156 className = clazz.getComponentType().getName(); 157 } else { 158 className = clazz.getName(); 159 } 160 lastDotIndex = className.lastIndexOf("."); 161 if (lastDotIndex > 0) { 162 return className.substring(0, lastDotIndex); 163 } 164 return ""; 165 } 166 }