001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.catalina.tribes.util;
019:
020: import java.text.MessageFormat;
021: import java.util.Hashtable;
022: import java.util.Locale;
023: import java.util.MissingResourceException;
024: import java.util.ResourceBundle;
025: import java.net.URLClassLoader;
026:
027: /**
028: * An internationalization / localization helper class which reduces
029: * the bother of handling ResourceBundles and takes care of the
030: * common cases of message formating which otherwise require the
031: * creation of Object arrays and such.
032: *
033: * <p>The StringManager operates on a package basis. One StringManager
034: * per package can be created and accessed via the getManager method
035: * call.
036: *
037: * <p>The StringManager will look for a ResourceBundle named by
038: * the package name given plus the suffix of "LocalStrings". In
039: * practice, this means that the localized information will be contained
040: * in a LocalStrings.properties file located in the package
041: * directory of the classpath.
042: *
043: * <p>Please see the documentation for java.util.ResourceBundle for
044: * more information.
045: *
046: * @author James Duncan Davidson [duncan@eng.sun.com]
047: * @author James Todd [gonzo@eng.sun.com]
048: */
049:
050: public class StringManager {
051:
052: /**
053: * The ResourceBundle for this StringManager.
054: */
055:
056: private ResourceBundle bundle;
057:
058: private static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
059: .getLog(StringManager.class);
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: String bundleName = packageName + ".LocalStrings";
072: try {
073: bundle = ResourceBundle.getBundle(bundleName);
074: return;
075: } catch (MissingResourceException ex) {
076: // Try from the current loader ( that's the case for trusted apps )
077: ClassLoader cl = Thread.currentThread()
078: .getContextClassLoader();
079: if (cl != null) {
080: try {
081: bundle = ResourceBundle.getBundle(bundleName,
082: Locale.getDefault(), cl);
083: return;
084: } catch (MissingResourceException ex2) {
085: }
086: }
087: if (cl == null)
088: cl = this .getClass().getClassLoader();
089:
090: if (log.isDebugEnabled())
091: log.debug("Can't find resource " + bundleName + " "
092: + cl);
093: if (cl instanceof URLClassLoader) {
094: if (log.isDebugEnabled())
095: log.debug(((URLClassLoader) cl).getURLs());
096: }
097: }
098: }
099:
100: /**
101: * Get a string from the underlying resource bundle.
102: *
103: * @param key The resource name
104: */
105: public String getString(String key) {
106: return MessageFormat.format(getStringInternal(key),
107: (Object[]) null);
108: }
109:
110: protected String getStringInternal(String key) {
111: if (key == null) {
112: String msg = "key is null";
113:
114: throw new NullPointerException(msg);
115: }
116:
117: String str = null;
118:
119: if (bundle == null)
120: return key;
121: try {
122: str = bundle.getString(key);
123: } catch (MissingResourceException mre) {
124: str = "Cannot find message associated with key '" + key
125: + "'";
126: }
127:
128: return str;
129: }
130:
131: /**
132: * Get a string from the underlying resource bundle and format
133: * it with the given set of arguments.
134: *
135: * @param key The resource name
136: * @param args Formatting directives
137: */
138:
139: public String getString(String key, Object[] args) {
140: String iString = null;
141: String value = getStringInternal(key);
142:
143: // this check for the runtime exception is some pre 1.1.6
144: // VM's don't do an automatic toString() on the passed in
145: // objects and barf out
146:
147: try {
148: // ensure the arguments are not null so pre 1.2 VM's don't barf
149: Object nonNullArgs[] = args;
150: for (int i = 0; i < args.length; i++) {
151: if (args[i] == null) {
152: if (nonNullArgs == args)
153: nonNullArgs = (Object[]) args.clone();
154: nonNullArgs[i] = "null";
155: }
156: }
157:
158: iString = MessageFormat.format(value, nonNullArgs);
159: } catch (IllegalArgumentException iae) {
160: StringBuffer buf = new StringBuffer();
161: buf.append(value);
162: for (int i = 0; i < args.length; i++) {
163: buf.append(" arg[" + i + "]=" + args[i]);
164: }
165: iString = buf.toString();
166: }
167: return iString;
168: }
169:
170: /**
171: * Get a string from the underlying resource bundle and format it
172: * with the given object argument. This argument can of course be
173: * a String object.
174: *
175: * @param key The resource name
176: * @param arg Formatting directive
177: */
178:
179: public String getString(String key, Object arg) {
180: Object[] args = new Object[] { arg };
181: return getString(key, args);
182: }
183:
184: /**
185: * Get a string from the underlying resource bundle and format it
186: * with the given object arguments. These arguments can of course
187: * be String objects.
188: *
189: * @param key The resource name
190: * @param arg1 Formatting directive
191: * @param arg2 Formatting directive
192: */
193:
194: public String getString(String key, Object arg1, Object arg2) {
195: Object[] args = new Object[] { arg1, arg2 };
196: return getString(key, args);
197: }
198:
199: /**
200: * Get a string from the underlying resource bundle and format it
201: * with the given object arguments. These arguments can of course
202: * be String objects.
203: *
204: * @param key The resource name
205: * @param arg1 Formatting directive
206: * @param arg2 Formatting directive
207: * @param arg3 Formatting directive
208: */
209:
210: public String getString(String key, Object arg1, Object arg2,
211: Object arg3) {
212: Object[] args = new Object[] { arg1, arg2, arg3 };
213: return getString(key, args);
214: }
215:
216: /**
217: * Get a string from the underlying resource bundle and format it
218: * with the given object arguments. These arguments can of course
219: * be String objects.
220: *
221: * @param key The resource name
222: * @param arg1 Formatting directive
223: * @param arg2 Formatting directive
224: * @param arg3 Formatting directive
225: * @param arg4 Formatting directive
226: */
227:
228: public String getString(String key, Object arg1, Object arg2,
229: Object arg3, Object arg4) {
230: Object[] args = new Object[] { arg1, arg2, arg3, arg4 };
231: return getString(key, args);
232: }
233:
234: // --------------------------------------------------------------
235: // STATIC SUPPORT METHODS
236: // --------------------------------------------------------------
237:
238: private static Hashtable managers = new Hashtable();
239:
240: /**
241: * Get the StringManager for a particular package. If a manager for
242: * a package already exists, it will be reused, else a new
243: * StringManager will be created and returned.
244: *
245: * @param packageName The package name
246: */
247:
248: public synchronized static StringManager getManager(
249: String packageName) {
250: StringManager mgr = (StringManager) managers.get(packageName);
251:
252: if (mgr == null) {
253: mgr = new StringManager(packageName);
254: managers.put(packageName, mgr);
255: }
256: return mgr;
257: }
258: }
|