1 /* 2 * Copyright (c) 2005, 2006 2007 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.jbi4ejb.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 @SuppressWarnings("unchecked") 54 private Messages(final Class clazz, final Locale locale) { 55 bundle = ResourceBundle.getBundle(getBundleName(clazz), locale, 56 clazz.getClassLoader()); 57 } 58 59 /** 60 * Factory method to create a <code>Messages</code> object from a 61 * <code>Class</code>. 62 * 63 * @param clazz the class used to find the resource bundle. Must not be 64 * <code>null</code>. 65 * @return a <code>Messages</code> object related to <code>clazz</code>, 66 * never <code>null</code>. The messages bundle used is related to 67 * the default locale. 68 */ 69 @SuppressWarnings("unchecked") 70 public static Messages getMessages(final Class clazz) { 71 return new Messages(clazz, Locale.getDefault()); 72 } 73 74 /** 75 * Factory method to create a <code>Messages</code> object from a 76 * <code>Class</code> and a <code>Locale</code>. 77 * 78 * @param clazz the class used to find the resource bundle. Must not be 79 * <code>null</code>. 80 * @param locale the <code>Locale</code> to find the correct resource 81 * bundle. If <code>null</code>, the default locale will be 82 * used. 83 * @return a <code>Messages</code> object related to <code>clazz</code> and 84 * <code>locale</code>, never <code>null</code>. 85 */ 86 @SuppressWarnings("unchecked") 87 public static Messages getMessages(final Class clazz, final Locale locale) { 88 if (locale == null) { 89 return new Messages(clazz, Locale.getDefault()); 90 } 91 return new Messages(clazz, locale); 92 } 93 94 /** 95 * Retrieves a localized <code>String</code> which may contains parameters. 96 * This method applies a <code>MessageFormat</code> to the value with the 97 * arguments provided. 98 * 99 * @param key the resource key to retrieve the (localized) message. 100 * @param args the optional <code>MessageFormat</code> arguments. 101 * @return the localized messaged related to the key <code>key</code> after 102 * the substitution of its parameters with values 103 * <code>args</code>. 104 */ 105 public String getString(final String key, final Object ... args) { 106 String rawValue; 107 108 try { 109 synchronized (bundle) { 110 rawValue = bundle.getString(key); 111 } 112 } catch (MissingResourceException e) { 113 return key; 114 } 115 try { 116 return MessageFormat.format(rawValue, args); 117 } catch (IllegalArgumentException e) { 118 return rawValue; 119 } 120 } 121 122 /** 123 * Determines the bundle name for a <code>Class</code>. 124 * 125 * @param clazz the <code>Class</code> object used to find the 126 * <code>ResourceBundle</code>. Must not be 127 * <code>null</code>. 128 * @return the name of the <code>ResourceBundle</code> related to 129 * <code>clazz</code>, ever different from <code>null</code>. 130 */ 131 @SuppressWarnings("unchecked") 132 private static String getBundleName(final Class clazz) { 133 String packageName = getPackageName(clazz); 134 135 if (packageName.length() == 0) { 136 return BUNDLE_NAME; 137 } 138 return packageName.concat(BUNDLE_NAME_SUFFIX); 139 } 140 141 /** 142 * Retrieves the package name for a <code>Class</code> object. 143 * If the class doesn't have a package, the empty string is returned. 144 * 145 * @param clazz the class to retrieve its package name. Must not be 146 * <code>null</code>. 147 * @return the package name for <code>clazz</code> if it exists, otherwise 148 * the empty string. 149 */ 150 @SuppressWarnings("unchecked") 151 private static String getPackageName(final Class clazz) { 152 Package pack = clazz.getPackage(); 153 String className; 154 int lastDotIndex; 155 156 if (pack != null) { 157 return pack.getName(); 158 } 159 160 if (clazz.isArray()) { 161 className = clazz.getComponentType().getName(); 162 } else { 163 className = clazz.getName(); 164 } 165 lastDotIndex = className.lastIndexOf("."); 166 if (lastDotIndex > 0) { 167 return className.substring(0, lastDotIndex); 168 } 169 return ""; 170 } 171 }