1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.tomcat.util.res;
19
20 import java.text.MessageFormat;
21 import java.util.Hashtable;
22 import java.util.Locale;
23 import java.util.MissingResourceException;
24 import java.util.ResourceBundle;
25
26 /**
27 * An internationalization / localization helper class which reduces
28 * the bother of handling ResourceBundles and takes care of the
29 * common cases of message formating which otherwise require the
30 * creation of Object arrays and such.
31 *
32 * <p>The StringManager operates on a package basis. One StringManager
33 * per package can be created and accessed via the getManager method
34 * call.
35 *
36 * <p>The StringManager will look for a ResourceBundle named by
37 * the package name given plus the suffix of "LocalStrings". In
38 * practice, this means that the localized information will be contained
39 * in a LocalStrings.properties file located in the package
40 * directory of the classpath.
41 *
42 * <p>Please see the documentation for java.util.ResourceBundle for
43 * more information.
44 *
45 * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
46 *
47 * @author James Duncan Davidson [duncan@eng.sun.com]
48 * @author James Todd [gonzo@eng.sun.com]
49 * @author Mel Martinez [mmartinez@g1440.com]
50 * @see java.util.ResourceBundle
51 */
52
53 public class StringManager {
54
55 /**
56 * The ResourceBundle for this StringManager.
57 */
58
59 private ResourceBundle bundle;
60 private Locale locale;
61
62 /**
63 * Creates a new StringManager for a given package. This is a
64 * private method and all access to it is arbitrated by the
65 * static getManager method call so that only one StringManager
66 * per package will be created.
67 *
68 * @param packageName Name of package to create StringManager for.
69 */
70
71 private StringManager(String packageName) {
72 this( packageName, Locale.getDefault() );
73 }
74
75 private StringManager(String packageName, Locale loc) {
76 String bundleName = packageName + ".LocalStrings";
77 bundle = ResourceBundle.getBundle(bundleName, loc);
78 // Get the actual locale, which may be different from the requested one
79 locale = bundle.getLocale();
80 }
81
82 private StringManager(ResourceBundle bundle )
83 {
84 this.bundle=bundle;
85 locale = bundle.getLocale();
86 }
87
88 /**
89 Get a string from the underlying resource bundle or return
90 null if the String is not found.
91
92 @param key to desired resource String
93 @return resource String matching <i>key</i> from underlying
94 bundle or null if not found.
95 @throws IllegalArgumentException if <i>key</i> is null.
96 */
97
98 public String getString(String key) {
99 if(key == null){
100 String msg = "key may not have a null value";
101
102 throw new IllegalArgumentException(msg);
103 }
104
105 String str = null;
106
107 try{
108 str = bundle.getString(key);
109 }catch(MissingResourceException mre){
110 //bad: shouldn't mask an exception the following way:
111 // str = "[cannot find message associated with key '" + key + "' due to " + mre + "]";
112 // because it hides the fact that the String was missing
113 // from the calling code.
114 //good: could just throw the exception (or wrap it in another)
115 // but that would probably cause much havoc on existing
116 // code.
117 //better: consistent with container pattern to
118 // simply return null. Calling code can then do
119 // a null check.
120 str = null;
121 }
122
123 return str;
124 }
125
126 /**
127 * Get a string from the underlying resource bundle and format
128 * it with the given set of arguments.
129 *
130 * @param key
131 * @param args
132 */
133
134 public String getString(String key, Object[] args) {
135 String iString = null;
136 String value = getString(key);
137
138 // this check for the runtime exception is some pre 1.1.6
139 // VM's don't do an automatic toString() on the passed in
140 // objects and barf out
141
142 try {
143 // ensure the arguments are not null so pre 1.2 VM's don't barf
144 if(args==null){
145 args = new Object[1];
146 }
147
148 Object[] nonNullArgs = args;
149 for (int i=0; i<args.length; i++) {
150 if (args[i] == null) {
151 if (nonNullArgs==args){
152 nonNullArgs=(Object[])args.clone();
153 }
154 nonNullArgs[i] = "null";
155 }
156 }
157 if( value==null ) value=key;
158 MessageFormat mf = new MessageFormat(value);
159 mf.setLocale(locale);
160 iString = mf.format(nonNullArgs, new StringBuffer(), null).toString();
161 } catch (IllegalArgumentException iae) {
162 StringBuffer buf = new StringBuffer();
163 buf.append(value);
164 for (int i = 0; i < args.length; i++) {
165 buf.append(" arg[" + i + "]=" + args[i]);
166 }
167 iString = buf.toString();
168 }
169 return iString;
170 }
171
172 /**
173 * Get a string from the underlying resource bundle and format it
174 * with the given object argument. This argument can of course be
175 * a String object.
176 *
177 * @param key
178 * @param arg
179 */
180
181 public String getString(String key, Object arg) {
182 Object[] args = new Object[] {arg};
183 return getString(key, args);
184 }
185
186 /**
187 * Get a string from the underlying resource bundle and format it
188 * with the given object arguments. These arguments can of course
189 * be String objects.
190 *
191 * @param key
192 * @param arg1
193 * @param arg2
194 */
195
196 public String getString(String key, Object arg1, Object arg2) {
197 Object[] args = new Object[] {arg1, arg2};
198 return getString(key, args);
199 }
200
201 /**
202 * Get a string from the underlying resource bundle and format it
203 * with the given object arguments. These arguments can of course
204 * be String objects.
205 *
206 * @param key
207 * @param arg1
208 * @param arg2
209 * @param arg3
210 */
211
212 public String getString(String key, Object arg1, Object arg2,
213 Object arg3) {
214 Object[] args = new Object[] {arg1, arg2, arg3};
215 return getString(key, args);
216 }
217
218 /**
219 * Get a string from the underlying resource bundle and format it
220 * with the given object arguments. These arguments can of course
221 * be String objects.
222 *
223 * @param key
224 * @param arg1
225 * @param arg2
226 * @param arg3
227 * @param arg4
228 */
229
230 public String getString(String key, Object arg1, Object arg2,
231 Object arg3, Object arg4) {
232 Object[] args = new Object[] {arg1, arg2, arg3, arg4};
233 return getString(key, args);
234 }
235 // --------------------------------------------------------------
236 // STATIC SUPPORT METHODS
237 // --------------------------------------------------------------
238
239 private static Hashtable managers = new Hashtable();
240
241 /**
242 * Get the StringManager for a particular package. If a manager for
243 * a package already exists, it will be reused, else a new
244 * StringManager will be created and returned.
245 *
246 * @param packageName The package name
247 */
248 public synchronized static StringManager getManager(String packageName) {
249 StringManager mgr = (StringManager)managers.get(packageName);
250 if (mgr == null) {
251 mgr = new StringManager(packageName);
252 managers.put(packageName, mgr);
253 }
254 return mgr;
255 }
256
257 /**
258 * Get the StringManager for a particular package. If a manager for
259 * a package already exists, it will be reused, else a new
260 * StringManager will be created and returned.
261 *
262 * @param bundle The resource bundle
263 */
264 public synchronized static StringManager getManager(ResourceBundle bundle) {
265 return new StringManager( bundle );
266 }
267
268 /**
269 * Get the StringManager for a particular package and Locale. If a manager for
270 * a package already exists, it will be reused, else a new
271 * StringManager will be created for that Locale and returned.
272 *
273 * @param packageName The package name
274 * @param loc The locale
275 */
276
277 public synchronized static StringManager getManager(String packageName,Locale loc) {
278 StringManager mgr = (StringManager)managers.get(packageName+"_"+loc.toString());
279 if (mgr == null) {
280 mgr = new StringManager(packageName,loc);
281 managers.put(packageName+"_"+loc.toString(), mgr);
282 }
283 return mgr;
284 }
285
286 }