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 }