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.catalina.util;
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: import java.net.URLClassLoader;
025:
026: /**
027: * An internationalization / localization helper class which reduces
028: * the bother of handling ResourceBundles and takes care of the
029: * common cases of message formating which otherwise require the
030: * creation of Object arrays and such.
031: *
032: * <p>The StringManager operates on a package basis. One StringManager
033: * per package can be created and accessed via the getManager method
034: * call.
035: *
036: * <p>The StringManager will look for a ResourceBundle named by
037: * the package name given plus the suffix of "LocalStrings". In
038: * practice, this means that the localized information will be contained
039: * in a LocalStrings.properties file located in the package
040: * directory of the classpath.
041: *
042: * <p>Please see the documentation for java.util.ResourceBundle for
043: * more information.
044: *
045: * @author James Duncan Davidson [duncan@eng.sun.com]
046: * @author James Todd [gonzo@eng.sun.com]
047: */
048:
049: public class StringManager {
050:
051: /**
052: * The ResourceBundle for this StringManager.
053: */
054:
055: private ResourceBundle bundle;
056:
057: /**
058: * Creates a new StringManager for a given package. This is a
059: * private method and all access to it is arbitrated by the
060: * static getManager method call so that only one StringManager
061: * per package will be created.
062: *
063: * @param packageName Name of package to create StringManager for.
064: */
065:
066: private StringManager(String packageName) {
067: String bundleName = packageName + ".LocalStrings";
068: try {
069: bundle = ResourceBundle.getBundle(bundleName);
070: return;
071: } catch (MissingResourceException ex) {
072: // Try from the current loader ( that's the case for trusted apps )
073: ClassLoader cl = Thread.currentThread()
074: .getContextClassLoader();
075: if (cl != null) {
076: try {
077: bundle = ResourceBundle.getBundle(bundleName,
078: Locale.getDefault(), cl);
079: return;
080: } catch (MissingResourceException ex2) {
081: }
082: }
083: if (cl == null)
084: cl = this .getClass().getClassLoader();
085:
086: System.out.println("Can't find resource " + bundleName
087: + " " + cl);
088: if (cl instanceof URLClassLoader) {
089: System.out.println(((URLClassLoader) cl).getURLs());
090: }
091: }
092: }
093:
094: /**
095: * Get a string from the underlying resource bundle.
096: *
097: * @param key The resource name
098: */
099: public String getString(String key) {
100: return MessageFormat.format(getStringInternal(key), null);
101: }
102:
103: protected String getStringInternal(String key) {
104: if (key == null) {
105: String msg = "key is null";
106:
107: throw new NullPointerException(msg);
108: }
109:
110: String str = null;
111:
112: if (bundle == null)
113: return key;
114: try {
115: str = bundle.getString(key);
116: } catch (MissingResourceException mre) {
117: str = "Cannot find message associated with key '" + key
118: + "'";
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 The resource name
129: * @param args Formatting directives
130: */
131:
132: public String getString(String key, Object[] args) {
133: String iString = null;
134: String value = getStringInternal(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: Object nonNullArgs[] = args;
143: for (int i = 0; i < args.length; i++) {
144: if (args[i] == null) {
145: if (nonNullArgs == args)
146: nonNullArgs = (Object[]) args.clone();
147: nonNullArgs[i] = "null";
148: }
149: }
150:
151: iString = MessageFormat.format(value, nonNullArgs);
152: } catch (IllegalArgumentException iae) {
153: StringBuffer buf = new StringBuffer();
154: buf.append(value);
155: for (int i = 0; i < args.length; i++) {
156: buf.append(" arg[" + i + "]=" + args[i]);
157: }
158: iString = buf.toString();
159: }
160: return iString;
161: }
162:
163: /**
164: * Get a string from the underlying resource bundle and format it
165: * with the given object argument. This argument can of course be
166: * a String object.
167: *
168: * @param key The resource name
169: * @param arg Formatting directive
170: */
171:
172: public String getString(String key, Object arg) {
173: Object[] args = new Object[] { arg };
174: return getString(key, args);
175: }
176:
177: /**
178: * Get a string from the underlying resource bundle and format it
179: * with the given object arguments. These arguments can of course
180: * be String objects.
181: *
182: * @param key The resource name
183: * @param arg1 Formatting directive
184: * @param arg2 Formatting directive
185: */
186:
187: public String getString(String key, Object arg1, Object arg2) {
188: Object[] args = new Object[] { arg1, arg2 };
189: return getString(key, args);
190: }
191:
192: /**
193: * Get a string from the underlying resource bundle and format it
194: * with the given object arguments. These arguments can of course
195: * be String objects.
196: *
197: * @param key The resource name
198: * @param arg1 Formatting directive
199: * @param arg2 Formatting directive
200: * @param arg3 Formatting directive
201: */
202:
203: public String getString(String key, Object arg1, Object arg2,
204: Object arg3) {
205: Object[] args = new Object[] { arg1, arg2, arg3 };
206: return getString(key, args);
207: }
208:
209: /**
210: * Get a string from the underlying resource bundle and format it
211: * with the given object arguments. These arguments can of course
212: * be String objects.
213: *
214: * @param key The resource name
215: * @param arg1 Formatting directive
216: * @param arg2 Formatting directive
217: * @param arg3 Formatting directive
218: * @param arg4 Formatting directive
219: */
220:
221: public String getString(String key, Object arg1, Object arg2,
222: Object arg3, Object arg4) {
223: Object[] args = new Object[] { arg1, arg2, arg3, arg4 };
224: return getString(key, args);
225: }
226:
227: // --------------------------------------------------------------
228: // STATIC SUPPORT METHODS
229: // --------------------------------------------------------------
230:
231: private static Hashtable managers = new Hashtable();
232:
233: /**
234: * Get the StringManager for a particular package. If a manager for
235: * a package already exists, it will be reused, else a new
236: * StringManager will be created and returned.
237: *
238: * @param packageName The package name
239: */
240:
241: public synchronized static StringManager getManager(
242: String packageName) {
243: StringManager mgr = (StringManager) managers.get(packageName);
244:
245: if (mgr == null) {
246: mgr = new StringManager(packageName);
247: managers.put(packageName, mgr);
248: }
249: return mgr;
250: }
251: }
|