View Javadoc
1 package org.apache.turbine.services.localization; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import java.util.Hashtable; 58 import java.util.Locale; 59 import java.util.ResourceBundle; 60 import java.util.MissingResourceException; 61 import javax.servlet.http.HttpServletRequest; 62 63 import org.apache.turbine.services.InitializationException; 64 import org.apache.turbine.services.TurbineBaseService; 65 import org.apache.turbine.services.resources.TurbineResources; 66 import org.apache.turbine.util.RunData; 67 import org.apache.turbine.util.Log; 68 import org.apache.turbine.util.StringUtils; 69 70 /*** 71 * <p>This class is the single point of access to all localization 72 * resources. It caches different ResourceBundles for different 73 * Locales.</p> 74 * 75 * <p>Usage example:</p> 76 * 77 * <blockquote><code><pre> 78 * LocalizationService ls = (LocalizationService) TurbineServices 79 * .getInstance().getService(LocalizationService.SERVICE_NAME); 80 * </pre></code></blockquote> 81 * 82 * <p>Then call one of four methods to retrieve a ResourceBundle: 83 * 84 * <ul> 85 * <li>getBundle("MyBundleName")</li> 86 * <li>getBundle("MyBundleName", httpAcceptLanguageHeader)</li> 87 * <li>etBundle("MyBundleName", HttpServletRequest)</li> 88 * <li>getBundle("MyBundleName", Locale)</li> 89 * <li>etc.</li> 90 * </ul></p> 91 * 92 * @author <a href="mailto:jm@mediaphil.de">Jonas Maurus</a> 93 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> 94 * @author <a href="mailto:novalidemail@foo.com">Frank Y. Kim</a> 95 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 96 */ 97 public class TurbineLocalizationService 98 extends TurbineBaseService 99 implements LocalizationService 100 { 101 /*** 102 * The ResourceBundles in this service. 103 * Key=bundle name 104 * Value=Hashtable containing ResourceBundles keyed by Locale. 105 */ 106 private Hashtable bundles = null; 107 108 /*** 109 * The list of default bundles to search. 110 */ 111 private String[] bundleNames = null; 112 113 /*** 114 * The name of the default locale to use (includes language and 115 * country). 116 */ 117 private Locale defaultLocale = null; 118 119 /*** The name of the default language to use. */ 120 private String defaultLanguage = null; 121 122 /*** The name of the default country to use. */ 123 private String defaultCountry = null; 124 125 /*** 126 * Constructor. 127 */ 128 public TurbineLocalizationService() 129 { 130 bundles = new Hashtable(); 131 } 132 133 /*** 134 * Called the first time the Service is used. 135 */ 136 public void init() 137 throws InitializationException 138 { 139 initBundleNames(null); 140 141 Locale jvmDefault = Locale.getDefault(); 142 defaultLanguage = TurbineResources 143 .getString("locale.default.language", 144 jvmDefault.getLanguage()).trim(); 145 defaultCountry = TurbineResources 146 .getString("locale.default.country", 147 jvmDefault.getCountry()).trim(); 148 defaultLocale = new Locale(defaultLanguage, defaultCountry); 149 setInit(true); 150 } 151 152 153 /*** 154 * Initialize list of default bundle names. 155 * 156 * @param names Ignored. 157 */ 158 protected void initBundleNames(String[] ignored) 159 { 160 bundleNames = 161 TurbineResources.getStringArray("locale.default.bundles"); 162 String name = TurbineResources.getString("locale.default.bundle"); 163 164 if (name != null && name.length() > 0) 165 { 166 // Using old-style single bundle name property. 167 if (bundleNames == null || bundleNames.length <= 0) 168 { 169 bundleNames = new String[] { name }; 170 } 171 else 172 { 173 // Prepend "default" bundle name. 174 String[] array = new String[bundleNames.length + 1]; 175 array[0] = name; 176 System.arraycopy(bundleNames, 0, array, 1, bundleNames.length); 177 bundleNames = array; 178 } 179 } 180 if (bundleNames == null) 181 { 182 bundleNames = new String[0]; 183 } 184 } 185 186 /*** 187 * Retrieves the name of the default bundle (as specified in the 188 * config file). 189 * @see org.apache.turbine.services.localization.LocalizationService#getDefaultBundleName() 190 */ 191 public String getDefaultBundleName() 192 { 193 return (bundleNames.length > 0 ? bundleNames[0] : ""); 194 } 195 196 /*** 197 * This method returns a ResourceBundle given the bundle name 198 * "DEFAULT" and the default Locale information supplied in 199 * TurbineProperties. 200 * 201 * @return A localized ResourceBundle. 202 */ 203 public ResourceBundle getBundle() 204 { 205 return getBundle(getDefaultBundleName(), (Locale) null); 206 } 207 208 /*** 209 * This method returns a ResourceBundle given the bundle name and 210 * the default Locale information supplied in TurbineProperties. 211 * 212 * @param bundleName Name of bundle. 213 * @return A localized ResourceBundle. 214 */ 215 public ResourceBundle getBundle(String bundleName) 216 { 217 return getBundle(bundleName, (Locale) null); 218 } 219 220 /*** 221 * This method returns a ResourceBundle given the bundle name and 222 * the Locale information supplied in the HTTP "Accept-Language" 223 * header. 224 * 225 * @param bundleName Name of bundle. 226 * @param languageHeader A String with the language header. 227 * @return A localized ResourceBundle. 228 */ 229 public ResourceBundle getBundle(String bundleName, String languageHeader) 230 { 231 return getBundle(bundleName, getLocale(languageHeader)); 232 } 233 234 /*** 235 * This method returns a ResourceBundle given the Locale 236 * information supplied in the HTTP "Accept-Language" header which 237 * is stored in HttpServletRequest. 238 * 239 * @param req HttpServletRequest. 240 * @return A localized ResourceBundle. 241 */ 242 public ResourceBundle getBundle(HttpServletRequest req) 243 { 244 return getBundle(getDefaultBundleName(), getLocale(req)); 245 } 246 247 /*** 248 * This method returns a ResourceBundle given the bundle name and 249 * the Locale information supplied in the HTTP "Accept-Language" 250 * header which is stored in HttpServletRequest. 251 * 252 * @param bundleName Name of the bundle to use if the request's 253 * locale cannot be resolved. 254 * @param req HttpServletRequest. 255 * @return A localized ResourceBundle. 256 */ 257 public ResourceBundle getBundle(String bundleName, HttpServletRequest req) 258 { 259 return getBundle(bundleName, getLocale(req)); 260 } 261 262 /*** 263 * This method returns a ResourceBundle given the Locale 264 * information supplied in the HTTP "Accept-Language" header which 265 * is stored in RunData. 266 * 267 * @param data Turbine information. 268 * @return A localized ResourceBundle. 269 */ 270 public ResourceBundle getBundle(RunData data) 271 { 272 return getBundle(getDefaultBundleName(), getLocale(data.getRequest())); 273 } 274 275 /*** 276 * This method returns a ResourceBundle given the bundle name and 277 * the Locale information supplied in the HTTP "Accept-Language" 278 * header which is stored in RunData. 279 * 280 * @param bundleName Name of bundle. 281 * @param data Turbine information. 282 * @return A localized ResourceBundle. 283 */ 284 public ResourceBundle getBundle(String bundleName, RunData data) 285 { 286 return getBundle(bundleName, getLocale(data.getRequest())); 287 } 288 289 /*** 290 * This method returns a ResourceBundle for the given bundle name 291 * and the given Locale. 292 * 293 * @param bundleName Name of bundle. 294 * @param locale A Locale. 295 * @return A localized ResourceBundle. 296 */ 297 public ResourceBundle getBundle(String bundleName, Locale locale) 298 { 299 // Assure usable inputs. 300 bundleName = (bundleName == null ? getDefaultBundleName() : bundleName.trim()); 301 if (locale == null) 302 { 303 locale = getLocale((String) null); 304 } 305 306 if ( bundles.containsKey(bundleName) ) 307 { 308 Hashtable locales = (Hashtable)bundles.get(bundleName); 309 310 if ( locales.containsKey(locale) ) 311 { 312 return (ResourceBundle)locales.get(locale); 313 } 314 else 315 { 316 // Try to create a ResourceBundle for this Locale. 317 ResourceBundle rb = ResourceBundle.getBundle(bundleName, 318 locale); 319 320 // Cache the ResourceBundle in memory. 321 locales.put( rb.getLocale(), rb ); 322 323 return rb; 324 } 325 } 326 else 327 { 328 // Try to create a ResourceBundle for this Locale. 329 ResourceBundle rb = ResourceBundle.getBundle(bundleName, 330 locale); 331 332 // Cache the ResourceBundle in memory. 333 Hashtable ht = new Hashtable(); 334 ht.put( locale, rb ); 335 336 // Can't call getLocale(), because that is jdk2. This 337 // needs to be changed back, since the above approach 338 // caches extra Locale and Bundle objects. 339 // ht.put( rb.getLocale(), rb ); 340 341 bundles.put( bundleName, ht ); 342 343 return rb; 344 } 345 } 346 347 /*** 348 * This method sets the name of the first bundle in the search 349 * list (the "default" bundle). 350 * 351 * @param defaultBundle Name of default bundle. 352 */ 353 public void setBundle(String defaultBundle) 354 { 355 if (bundleNames.length > 0) 356 { 357 bundleNames[0] = defaultBundle; 358 } 359 else 360 { 361 synchronized (this) 362 { 363 if (bundleNames.length <= 0) 364 { 365 bundleNames = new String[] { defaultBundle }; 366 } 367 } 368 } 369 } 370 371 /*** 372 * @see org.apache.turbine.services.localization.LocalizationService#getLocale(HttpServletRequest) 373 */ 374 public final Locale getLocale(HttpServletRequest req) 375 { 376 return getLocale(req.getHeader(ACCEPT_LANGUAGE)); 377 } 378 379 /*** 380 * @see org.apache.turbine.services.localization.LocalizationService#getLocale(String) 381 */ 382 public Locale getLocale(String header) 383 { 384 if (!StringUtils.isEmpty(header)) 385 { 386 LocaleTokenizer tok = new LocaleTokenizer(header); 387 if (tok.hasNext()) 388 { 389 return (Locale) tok.next(); 390 } 391 } 392 393 // Couldn't parse locale. 394 return defaultLocale; 395 } 396 397 398 /*** 399 * @exception MissingResourceException Specified key cannot be matched. 400 * @see org.apache.turbine.services.localization.LocalizationService#getString(String, Locale, String) 401 */ 402 public String getString(String bundleName, Locale locale, String key) 403 { 404 String value = null; 405 406 if (locale == null) 407 { 408 locale = getLocale((String) null); 409 } 410 411 // Look for text in requested bundle. 412 ResourceBundle rb = getBundle(bundleName, locale); 413 value = getStringOrNull(rb, key); 414 415 // Look for text in list of default bundles. 416 if (value == null && bundleNames.length > 0) 417 { 418 String name; 419 for (int i = 0; i < bundleNames.length; i++) 420 { 421 name = bundleNames[i]; 422 //System.out.println("getString(): name=" + name + 423 // ", locale=" + locale + ", i=" + i); 424 if (!name.equals(bundleName)) 425 { 426 rb = getBundle(name, locale); 427 value = getStringOrNull(rb, key); 428 if (value != null) 429 { 430 locale = rb.getLocale(); 431 break; 432 } 433 } 434 } 435 } 436 437 if (value == null) 438 { 439 String loc = locale.toString(); 440 Log.debug(LocalizationService.SERVICE_NAME + 441 " noticed missing resource: " + 442 "bundleName=" + bundleName + ", locale=" + loc + 443 ", key=" + key); 444 // Text not found in requested or default bundles. 445 throw new MissingResourceException(bundleName, loc, key); 446 } 447 448 return value; 449 } 450 451 /*** 452 * Gets localized text from a bundle if it's there. Otherwise, 453 * returns <code>null</code> (ignoring a possible 454 * <code>MissingResourceException</code>). 455 */ 456 protected final String getStringOrNull(ResourceBundle rb, String key) 457 { 458 if (rb != null) 459 { 460 try 461 { 462 return rb.getString(key); 463 } 464 catch (MissingResourceException ignored) 465 { 466 } 467 } 468 return null; 469 } 470 471 }

This page was automatically generated by Maven