001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.tomcat.util.res;
018:
019: import java.text.MessageFormat;
020: import java.util.Hashtable;
021: import java.util.Locale;
022: import java.util.MissingResourceException;
023: import java.util.ResourceBundle;
024:
025: /**
026: * An internationalization / localization helper class which reduces
027: * the bother of handling ResourceBundles and takes care of the
028: * common cases of message formating which otherwise require the
029: * creation of Object arrays and such.
030: *
031: * <p>The StringManager operates on a package basis. One StringManager
032: * per package can be created and accessed via the getManager method
033: * call.
034: *
035: * <p>The StringManager will look for a ResourceBundle named by
036: * the package name given plus the suffix of "LocalStrings". In
037: * practice, this means that the localized information will be contained
038: * in a LocalStrings.properties file located in the package
039: * directory of the classpath.
040: *
041: * <p>Please see the documentation for java.util.ResourceBundle for
042: * more information.
043: *
044: * @version $Revision: 1.7 $ $Date: 2004/05/11 22:11:01 $
045: *
046: * @author James Duncan Davidson [duncan@eng.sun.com]
047: * @author James Todd [gonzo@eng.sun.com]
048: * @author Mel Martinez [mmartinez@g1440.com]
049: * @see java.util.ResourceBundle
050: */
051:
052: public class StringManager {
053:
054: /**
055: * The ResourceBundle for this StringManager.
056: */
057:
058: private ResourceBundle bundle;
059: private Locale locale;
060:
061: /**
062: * Creates a new StringManager for a given package. This is a
063: * private method and all access to it is arbitrated by the
064: * static getManager method call so that only one StringManager
065: * per package will be created.
066: *
067: * @param packageName Name of package to create StringManager for.
068: */
069:
070: private StringManager(String packageName) {
071: this (packageName, Locale.getDefault());
072: }
073:
074: private StringManager(String packageName, Locale loc) {
075: String bundleName = packageName + ".LocalStrings";
076: bundle = ResourceBundle.getBundle(bundleName, loc);
077: // Get the actual locale, which may be different from the requested one
078: locale = bundle.getLocale();
079: }
080:
081: private StringManager(ResourceBundle bundle) {
082: this .bundle = bundle;
083: locale = bundle.getLocale();
084: }
085:
086: /**
087: Get a string from the underlying resource bundle or return
088: null if the String is not found.
089:
090: @param key to desired resource String
091: @return resource String matching <i>key</i> from underlying
092: bundle or null if not found.
093: @throws IllegalArgumentException if <i>key</i> is null.
094: */
095:
096: public String getString(String key) {
097: if (key == null) {
098: String msg = "key may not have a null value";
099:
100: throw new IllegalArgumentException(msg);
101: }
102:
103: String str = null;
104:
105: try {
106: str = bundle.getString(key);
107: } catch (MissingResourceException mre) {
108: //bad: shouldn't mask an exception the following way:
109: // str = "[cannot find message associated with key '" + key + "' due to " + mre + "]";
110: // because it hides the fact that the String was missing
111: // from the calling code.
112: //good: could just throw the exception (or wrap it in another)
113: // but that would probably cause much havoc on existing
114: // code.
115: //better: consistent with container pattern to
116: // simply return null. Calling code can then do
117: // a null check.
118: str = null;
119: }
120:
121: return str;
122: }
123:
124: /**
125: * Get a string from the underlying resource bundle and format
126: * it with the given set of arguments.
127: *
128: * @param key
129: * @param args
130: */
131:
132: public String getString(String key, Object[] args) {
133: String iString = null;
134: String value = getString(key);
135:
136: // this check for the runtime exception is some pre 1.1.6
137: // VM's don't do an automatic toString() on the passed in
138: // objects and barf out
139:
140: try {
141: // ensure the arguments are not null so pre 1.2 VM's don't barf
142: if (args == null) {
143: args = new Object[1];
144: }
145:
146: Object[] nonNullArgs = args;
147: for (int i = 0; i < args.length; i++) {
148: if (args[i] == null) {
149: if (nonNullArgs == args) {
150: nonNullArgs = (Object[]) args.clone();
151: }
152: nonNullArgs[i] = "null";
153: }
154: }
155: if (value == null)
156: value = key;
157: MessageFormat mf = new MessageFormat(value);
158: mf.setLocale(locale);
159: iString = mf.format(nonNullArgs, new StringBuffer(), null)
160: .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: // --------------------------------------------------------------
237: // STATIC SUPPORT METHODS
238: // --------------------------------------------------------------
239:
240: private static Hashtable managers = new Hashtable();
241:
242: /**
243: * Get the StringManager for a particular package. If a manager for
244: * a package already exists, it will be reused, else a new
245: * StringManager will be created and returned.
246: *
247: * @param packageName
248: */
249:
250: public synchronized static StringManager getManager(
251: String packageName) {
252: StringManager mgr = (StringManager) managers.get(packageName);
253: if (mgr == null) {
254: mgr = new StringManager(packageName);
255: managers.put(packageName, mgr);
256: }
257: return mgr;
258: }
259:
260: /**
261: * Get the StringManager for a particular package. If a manager for
262: * a package already exists, it will be reused, else a new
263: * StringManager will be created and returned.
264: *
265: * @param packageName
266: */
267: public synchronized static StringManager getManager(
268: ResourceBundle bundle) {
269: return new StringManager(bundle);
270: }
271:
272: /**
273: * Get the StringManager for a particular package and Locale. If a manager for
274: * a package already exists, it will be reused, else a new
275: * StringManager will be created for that Locale and returned.
276: *
277: *
278: * @param packageName
279: */
280:
281: public synchronized static StringManager getManager(
282: String packageName, Locale loc) {
283: StringManager mgr = (StringManager) managers.get(packageName
284: + "_" + loc.toString());
285: if (mgr == null) {
286: mgr = new StringManager(packageName, loc);
287: managers.put(packageName + "_" + loc.toString(), mgr);
288: }
289: return mgr;
290: }
291:
292: }
|