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