001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.jsp;
031:
032: import com.caucho.loader.Environment;
033: import com.caucho.loader.EnvironmentLocal;
034: import com.caucho.log.Log;
035: import com.caucho.util.L10N;
036: import com.caucho.util.TimedCache;
037: import com.caucho.vfs.Depend;
038: import com.caucho.vfs.Path;
039: import com.caucho.vfs.ReadStream;
040:
041: import javax.servlet.jsp.jstl.fmt.LocalizationContext;
042: import java.io.InputStream;
043: import java.util.Enumeration;
044: import java.util.Locale;
045: import java.util.PropertyResourceBundle;
046: import java.util.ResourceBundle;
047: import java.util.logging.Logger;
048:
049: /**
050: * Manages i18n bundles
051: */
052: public class BundleManager {
053: private static final L10N L = new L10N(BundleManager.class);
054: private static final Logger log = Log.open(BundleManager.class);
055:
056: static LocalizationContext NULL_BUNDLE = new LocalizationContext();
057:
058: private static EnvironmentLocal<BundleManager> _envBundle = new EnvironmentLocal<BundleManager>();
059:
060: private TimedCache<String, LocalizationContext> _bundleCache;
061:
062: private BundleManager() {
063: long updateInterval = Environment.getDependencyCheckInterval();
064:
065: _bundleCache = new TimedCache(256, updateInterval);
066: }
067:
068: /**
069: * Returns the environment's bundle.
070: */
071: public static BundleManager create() {
072: BundleManager manager;
073:
074: synchronized (_envBundle) {
075: manager = _envBundle.get();
076: if (manager == null) {
077: manager = new BundleManager();
078: _envBundle.set(manager);
079: }
080: }
081:
082: return manager;
083: }
084:
085: /**
086: * Returns the named ResourceBundle.
087: */
088: public LocalizationContext getBundle(String name, String cacheKey,
089: Enumeration<Locale> locales) {
090: LocalizationContext cachedValue = _bundleCache.get(cacheKey);
091:
092: if (cachedValue != null)
093: return cachedValue == NULL_BUNDLE ? null : cachedValue;
094:
095: while (locales.hasMoreElements()) {
096: Locale locale = locales.nextElement();
097:
098: LocalizationContext bundle = getBundle(name, locale);
099:
100: if (bundle != null) {
101: _bundleCache.put(cacheKey, bundle);
102: return bundle;
103: }
104: }
105:
106: _bundleCache.put(cacheKey, NULL_BUNDLE);
107:
108: return null;
109: }
110:
111: /**
112: * Returns the named ResourceBundle.
113: */
114: public LocalizationContext getBundle(String name, Locale locale) {
115: String cacheName = (name + '_' + locale.getLanguage() + '_'
116: + locale.getCountry() + '_' + locale.getVariant());
117:
118: LocalizationContext bundle;
119:
120: bundle = _bundleCache.get(cacheName);
121:
122: if (bundle != null)
123: return bundle != NULL_BUNDLE ? bundle : null;
124:
125: String fullName = cacheName;
126:
127: ResourceBundle resourceBundle;
128: resourceBundle = getBaseBundle(fullName);
129: if (resourceBundle != null) {
130: bundle = new LocalizationContext(resourceBundle, locale);
131: _bundleCache.put(cacheName, bundle);
132: return bundle;
133: }
134:
135: fullName = name + '_' + locale.getLanguage() + '_'
136: + locale.getCountry();
137: resourceBundle = getBaseBundle(fullName);
138: if (resourceBundle != null) {
139: bundle = new LocalizationContext(resourceBundle, locale);
140: _bundleCache.put(cacheName, bundle);
141: return bundle;
142: }
143:
144: fullName = name + '_' + locale.getLanguage();
145: resourceBundle = getBaseBundle(fullName);
146: if (resourceBundle != null) {
147: bundle = new LocalizationContext(resourceBundle, locale);
148: _bundleCache.put(cacheName, bundle);
149: return bundle;
150: }
151:
152: _bundleCache.put(cacheName, NULL_BUNDLE);
153:
154: return null;
155: }
156:
157: /**
158: * Returns the named ResourceBundle.
159: */
160: public LocalizationContext getBundle(String name) {
161: if (name == null)
162: return null;
163:
164: LocalizationContext bundle = _bundleCache.get(name);
165: if (bundle != null)
166: return bundle != NULL_BUNDLE ? bundle : null;
167:
168: ResourceBundle resourceBundle = getBaseBundle(name);
169: if (resourceBundle != null) {
170: bundle = new LocalizationContext(resourceBundle);
171: _bundleCache.put(name, bundle);
172: return bundle;
173: }
174:
175: _bundleCache.put(name, NULL_BUNDLE);
176:
177: return null;
178: }
179:
180: /**
181: * Returns the base resource bundle.
182: */
183: private ResourceBundle getBaseBundle(String name) {
184: ClassLoader loader = Thread.currentThread()
185: .getContextClassLoader();
186:
187: try {
188: Class cl = Class.forName(name, false, loader);
189:
190: if (cl != null) {
191: ResourceBundle rb = (ResourceBundle) cl.newInstance();
192:
193: if (rb != null)
194: return rb;
195: }
196: } catch (Throwable e) {
197: }
198:
199: try {
200: InputStream is = loader.getResourceAsStream(name.replace(
201: '.', '/')
202: + ".properties");
203:
204: if (is instanceof ReadStream) {
205: Path path = ((ReadStream) is).getPath();
206: Environment.addDependency(path.createDepend());
207: }
208:
209: ResourceBundle bundle = new PropertyResourceBundle(is);
210:
211: is.close();
212:
213: return bundle;
214: } catch (Exception e) {
215: }
216:
217: return null;
218: }
219: }
|