001: package org.tanukisoftware.wrapper.resources;
002:
003: /*
004: * Copyright (c) 1999, 2006 Tanuki Software Inc.
005: *
006: * Permission is hereby granted, free of charge, to any person
007: * obtaining a copy of the Java Service Wrapper and associated
008: * documentation files (the "Software"), to deal in the Software
009: * without restriction, including without limitation the rights
010: * to use, copy, modify, merge, publish, distribute, sub-license,
011: * and/or sell copies of the Software, and to permit persons to
012: * whom the Software is furnished to do so, subject to the
013: * following conditions:
014: *
015: * The above copyright notice and this permission notice shall be
016: * included in all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
020: * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
021: * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
022: * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
023: * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
024: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
025: * OTHER DEALINGS IN THE SOFTWARE.
026: *
027: *
028: * Portions of the Software have been derived from source code
029: * developed by Silver Egg Technology under the following license:
030: *
031: * Copyright (c) 2001 Silver Egg Technology
032: *
033: * Permission is hereby granted, free of charge, to any person
034: * obtaining a copy of this software and associated documentation
035: * files (the "Software"), to deal in the Software without
036: * restriction, including without limitation the rights to use,
037: * copy, modify, merge, publish, distribute, sub-license, and/or
038: * sell copies of the Software, and to permit persons to whom the
039: * Software is furnished to do so, subject to the following
040: * conditions:
041: *
042: * The above copyright notice and this permission notice shall be
043: * included in all copies or substantial portions of the Software.
044: */
045:
046: import java.util.Hashtable;
047: import java.util.MissingResourceException;
048: import java.util.ResourceBundle;
049: import java.text.MessageFormat;
050:
051: /**
052: * Some helper functions for handling i18n issues. One instance of this class
053: * should be created for each resource.<P>
054: *
055: * The ResourceManager is created by a call to <CODE>getResourceManager()</CODE>.
056: * The (optional) parameter is the name of the desired resource, not including the
057: * <code>.properties</code> suffix.
058: *
059: * For example,<P>
060: * <CODE>
061: * ResourceManager res = getResourceBundle();
062: * </CODE>
063: * <P>to get the default resources, or<P>
064: * <CODE>
065: * ResourceManager res = getResourceBundle("sql");
066: * </CODE>
067: * <P>
068: * to load the resources in <code>sql.properties</code>.
069: *
070: * To use the ResourceManager make a call to any of the <CODE>format()</CODE>
071: * methods. If a string is not found in the bundle the key is returned and a
072: * message is logged to the debug channel for this class.
073: *
074: * @author Leif Mortenson <leif@tanukisoftware.com>
075: */
076: public class ResourceManager {
077: private static Hashtable m_resources = new Hashtable();
078:
079: /**
080: * Whenever the Default Locale of the JVM is changed, then any existing
081: * resource bundles will need to update their values. The
082: * _classRefreshCounter static variable gets updated whenever a refresh
083: * is done. The m_refreshCounter variable then is used to tell whether
084: * an individual ResourceManager is up to date or not.
085: */
086: private int m_refreshCounter;
087: private static int m_staticRefreshCounter = 0;
088:
089: /**
090: * The ResourceBundle for this locale.
091: */
092: private ResourceBundle m_bundle;
093: private String m_bundleName;
094:
095: /**
096: * Private Constructor.
097: */
098: private ResourceManager(String resourceName) {
099: // Resolve the bundle name based on this class so that it will work correctly with obfuscators.
100: String className = this .getClass().getName();
101: // Strip off the class name at the end, keeping the ending '.'
102: int pos = className.lastIndexOf('.');
103: if (pos > 0) {
104: m_bundleName = className.substring(0, pos + 1);
105: } else {
106: m_bundleName = "";
107: }
108:
109: m_bundleName += resourceName;
110:
111: // Now load the bundle for the current Locale
112: refreshBundle();
113: }
114:
115: private void refreshBundle() {
116: try {
117: m_bundle = ResourceBundle.getBundle(m_bundleName);
118: } catch (MissingResourceException e) {
119: System.out.println(e);
120: }
121:
122: m_refreshCounter = m_staticRefreshCounter;
123: }
124:
125: /**
126: * Returns the default resource manager.
127: * An instance of the ResourceManager class is created the first
128: * time the method is called.
129: */
130: public static ResourceManager getResourceManager() {
131: return getResourceManager(null);
132: }
133:
134: /**
135: * Returns the named resource manager.
136: * An instance of the ResourceManager class is created the first
137: * time the method is called.
138: *
139: * @param resourceName The name of the desired resource
140: */
141: public static synchronized ResourceManager getResourceManager(
142: String resourceName) {
143: if (resourceName == null) {
144: resourceName = "resource";
145: }
146: ResourceManager resource = (ResourceManager) m_resources
147: .get(resourceName);
148: if (resource == null) {
149: resource = new ResourceManager(resourceName);
150: m_resources.put(resourceName, resource);
151: }
152: return resource;
153: }
154:
155: /**
156: * Clears the resource manager's cache of bundles (this should be called
157: * if the default locale for the application changes).
158: */
159: public static synchronized void refresh() {
160: m_resources = new Hashtable();
161: m_staticRefreshCounter++;
162: }
163:
164: private String getString(String key) {
165: // Make sure that the ResourceManager is up to date in a thread safe way
166: synchronized (this ) {
167: if (m_refreshCounter != m_staticRefreshCounter) {
168: refreshBundle();
169: }
170: }
171:
172: String msg;
173: if (m_bundle == null) {
174: msg = key;
175: } else {
176: try {
177: msg = m_bundle.getString(key);
178: } catch (MissingResourceException ex) {
179: msg = key;
180: System.out.println(key
181: + " is missing from resource bundle \""
182: + m_bundleName + "\"");
183: }
184: }
185:
186: return msg;
187: }
188:
189: /**
190: * Returns a string that has been obtained from the resource manager
191: *
192: * @param key The string that is the key to the translated message
193: *
194: */
195: public String format(String key) {
196: return getString(key);
197: }
198:
199: /**
200: * Returns a string that has been obtained from the resource manager then
201: * formatted using the passed parameters.
202: *
203: * @param pattern The string that is the key to the translated message
204: * @param o0 The param passed to format replaces {0}
205: *
206: */
207: public String format(String pattern, Object o0) {
208: return MessageFormat.format(getString(pattern),
209: new Object[] { o0 });
210: }
211:
212: /**
213: * Returns a string that has been obtained from the resource manager then
214: * formatted using the passed parameters.
215: *
216: * @param pattern The string that is the key to the translated message
217: * @param o0 The param passed to format replaces {0}
218: * @param o1 The param passed to format replaces {1}
219: *
220: */
221: public String format(String pattern, Object o0, Object o1) {
222: return MessageFormat.format(getString(pattern), new Object[] {
223: o0, o1 });
224: }
225:
226: /**
227: * Returns a string that has been obtained from the resource manager then
228: * formatted using the passed parameters.
229: *
230: * @param pattern The string that is the key to the translated message
231: * @param o0 The param passed to format replaces {0}
232: * @param o1 The param passed to format replaces {1}
233: * @param o2 The param passed to format replaces {2}
234: *
235: */
236: public String format(String pattern, Object o0, Object o1, Object o2) {
237: return MessageFormat.format(getString(pattern), new Object[] {
238: o0, o1, o2 });
239: }
240:
241: /**
242: * Returns a string that has been obtained from the resource manager then
243: * formatted using the passed parameters.
244: *
245: * @param pattern The string that is the key to the translated message
246: * @param o0 The param passed to format replaces {0}
247: * @param o1 The param passed to format replaces {1}
248: * @param o2 The param passed to format replaces {2}
249: * @param o3 The param passed to format replaces {3}
250: *
251: */
252: public String format(String pattern, Object o0, Object o1,
253: Object o2, Object o3) {
254: return MessageFormat.format(getString(pattern), new Object[] {
255: o0, o1, o2, o3 });
256: }
257:
258: // add more if you need them...
259: }
|