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 }