001: /*
002: * regain - A file search engine providing plenty of formats
003: * Copyright (C) 2004 Til Schneider
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Contact: Til Schneider, info@murfman.de
020: *
021: * CVS information:
022: * $RCSfile$
023: * $Source$
024: * $Date: 2005-08-10 08:26:23 +0200 (Mi, 10 Aug 2005) $
025: * $Author: til132 $
026: * $Revision: 154 $
027: */
028: package net.sf.regain.util.io;
029:
030: import java.net.MalformedURLException;
031: import java.net.URL;
032: import java.net.URLClassLoader;
033: import java.text.MessageFormat;
034: import java.util.HashMap;
035: import java.util.Locale;
036: import java.util.MissingResourceException;
037: import java.util.ResourceBundle;
038:
039: import net.sf.regain.RegainToolkit;
040:
041: import org.apache.log4j.Logger;
042:
043: /**
044: *
045: * @author Til Schneider, www.murfman.de
046: */
047: public class Localizer {
048:
049: /** The logger for this class. */
050: private static Logger mLog = Logger.getLogger(Localizer.class
051: .getName());
052:
053: /** The ResourceBundle to get the messages from. */
054: private ResourceBundle mBundle;
055:
056: /** The prefix to put before every key. */
057: private String mKeyPrefix;
058:
059: /**
060: * Holds for a directory (File) an URLClassLoader that loads ressources from
061: * that directory (URLClassLoader).
062: */
063: private static HashMap mFileClassLoaderHash;
064:
065: /**
066: * Creates a new instance of Localizer.
067: *
068: * @param baseurl The URL to load the resource bundle from.
069: * @param basename The basename of the resource bundle to load.
070: * @param locale the locale to create the localizer for.
071: */
072: public Localizer(URL baseurl, String basename, Locale locale) {
073: try {
074: URLClassLoader loader = getClassLoader(baseurl);
075: mBundle = ResourceBundle
076: .getBundle(basename, locale, loader);
077: } catch (Throwable thr) {
078: mLog.error("ResourceBundle not found: '" + basename + "'",
079: thr);
080: }
081:
082: mKeyPrefix = "";
083: }
084:
085: /**
086: * Creates a new instance of Localizer.
087: *
088: * @param clazz The class to create the Localizer for.
089: */
090: public Localizer(Class clazz) {
091: this (clazz, Locale.getDefault());
092: }
093:
094: /**
095: * Creates a new instance of Localizer.
096: *
097: * @param clazz The class to create the Localizer for.
098: * @param locale the locale to create the localizer for.
099: */
100: public Localizer(Class clazz, Locale locale) {
101: String className = clazz.getName();
102: String packageName;
103: int lastDot = className.lastIndexOf('.');
104: if (lastDot == -1) {
105: mKeyPrefix = className + ".";
106: packageName = "";
107: } else {
108: mKeyPrefix = className.substring(lastDot + 1) + ".";
109: packageName = className.substring(0, lastDot);
110: }
111:
112: // Get the bundle
113: do {
114: // Try this package
115: String basename = (packageName.length() == 0) ? "msg"
116: : (packageName + ".msg");
117: try {
118: mBundle = ResourceBundle.getBundle(basename, locale,
119: clazz.getClassLoader());
120: } catch (MissingResourceException exc) {
121: }
122:
123: // Check whether we have to check the next package
124: if (mBundle == null) {
125: if (packageName.length() == 0) {
126: // We already tried all packages -> Give up
127: mLog.error("ResourceBundle not found for class '"
128: + clazz + "'");
129: return;
130: }
131:
132: lastDot = packageName.lastIndexOf('.');
133: if (lastDot == -1) {
134: packageName = "";
135: } else {
136: packageName = packageName.substring(0, lastDot);
137: }
138: }
139: } while (mBundle == null);
140: }
141:
142: /**
143: * Gets a class loader that loads ressources from a directory.
144: *
145: * @param baseurl The URL to load the ressources from.
146: * @return The class loader
147: * @throws MalformedURLException If the file could not be converted to an URL.
148: */
149: private static synchronized URLClassLoader getClassLoader(
150: URL baseurl) throws MalformedURLException {
151: if (mFileClassLoaderHash == null) {
152: mFileClassLoaderHash = new HashMap();
153: }
154:
155: String baseurlAsString = baseurl.toExternalForm();
156: URLClassLoader loader = (URLClassLoader) mFileClassLoaderHash
157: .get(baseurlAsString);
158: if (loader == null) {
159: loader = new URLClassLoader(new URL[] { baseurl });
160: mFileClassLoaderHash.put(baseurlAsString, loader);
161: }
162:
163: return loader;
164: }
165:
166: /**
167: * Gets a localized message.
168: *
169: * @param key The key of the message.
170: * @param defaultMsg The default message. (english)
171: * @param arg1 The argument that should replace <CODE>{0}</CODE>.
172: * @return a localized message.
173: */
174: public String msg(String key, String defaultMsg, Object arg1) {
175: return msg(key, defaultMsg, new Object[] { arg1 });
176: }
177:
178: /**
179: * Gets a localized message.
180: *
181: * @param key The key of the message.
182: * @param defaultMsg The default message. (english)
183: * @param arg1 The argument that should replace <CODE>{0}</CODE>.
184: * @param arg2 The argument that should replace <CODE>{1}</CODE>.
185: * @return a localized message.
186: */
187: public String msg(String key, String defaultMsg, Object arg1,
188: Object arg2) {
189: return msg(key, defaultMsg, new Object[] { arg1, arg2 });
190: }
191:
192: /**
193: * Gets a localized message.
194: *
195: * @param key The key of the message.
196: * @param defaultMsg The default message. (english)
197: * @param arg1 The argument that should replace <CODE>{0}</CODE>.
198: * @param arg2 The argument that should replace <CODE>{1}</CODE>.
199: * @param arg3 The argument that should replace <CODE>{2}</CODE>.
200: * @return a localized message.
201: */
202: public String msg(String key, String defaultMsg, Object arg1,
203: Object arg2, Object arg3) {
204: return msg(key, defaultMsg, new Object[] { arg1, arg2, arg3 });
205: }
206:
207: /**
208: * Gets a localized message.
209: *
210: * @param key The key of the message.
211: * @param defaultMsg The default message. (english)
212: * @param args The arguments that should replace the appropriate place holder.
213: * See {@link java.text.MessageFormat} for details.
214: * @return a localized message.
215: */
216: public String msg(String key, String defaultMsg, Object[] args) {
217: String msg = msg(key, defaultMsg);
218:
219: // Workaround: The MessageFormat uses the ' char for quoting strings.
220: // so the "{0}" in "AB '{0}' CD" will not be replaced.
221: // In order to avoid this we quote every ' with '', so
222: // everthing will be replaced as expected.
223: msg = RegainToolkit.replace(msg, "'", "''");
224:
225: MessageFormat format = new MessageFormat(msg, mBundle
226: .getLocale());
227: return format.format(args);
228: }
229:
230: /**
231: * Gets a localized message.
232: *
233: * @param key The key of the message.
234: * @param defaultMsg The default message. (english)
235: * @return a localized message.
236: */
237: public String msg(String key, String defaultMsg) {
238: key = mKeyPrefix + key;
239:
240: String msg = null;
241: if (mBundle != null) {
242: try {
243: msg = mBundle.getString(key);
244: } catch (MissingResourceException exc) {
245: }
246: }
247:
248: if (msg == null) {
249: return "[" + key + "#" + defaultMsg + "]";
250: } else {
251: return msg;
252: }
253: }
254:
255: }
|