001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: I18n.java,v 1.3 2008/06/25 05:41:41 qcheng Exp $ 026 * 027 */ 028 029/** 030 * Portions Copyrighted [2011] [ForgeRock AS] 031 */ 032package com.iplanet.services.util; 033 034import java.io.UnsupportedEncodingException; 035import java.text.DateFormat; 036import java.text.MessageFormat; 037import java.util.Date; 038import java.util.HashMap; 039import java.util.Map; 040import java.util.ResourceBundle; 041import java.util.StringTokenizer; 042import java.util.TimeZone; 043 044/** 045 * The <code>I18n</code> class provides methods for applications and services 046 * to internationalize their messages. 047 * <p> 048 * In order for <code>I18n</code> to internationalize messages, it needs to 049 * determine the resource bundle name, i.e., properties file name. 050 * <code>I18n</code> supports two techniques by which applications and 051 * services can specify their I18N resource bundle name. The recommendation is 052 * to specify them during service (or application) registration via <b> SMS</b> 053 * using a XML file (see <code>com.iplanet.services.ServiceManager 054 * </code> and 055 * service registration DTD). The XML file could specify the resource bundle 056 * name (the attribute defined in the DTD is <code>i18nFileName</code>) and 057 * optionally URL of the jar file which contains the property file (the 058 * attribute defined in the DTD is <code>resourceBundleURL</code>). If URL 059 * for the jar file is not specified it is assumed that the resource bundle is 060 * in the <code> 061 * CLASSPATH</code>. Using this technique it is possible to 062 * customize resource bundle name and URL of the jar file by using SMS APIs, 063 * commands (CLI) or GUI. The solution makes internationalization of messages 064 * very dynamic and highly customizable. 065 * <p> 066 * <code>I18n</code> class be instantiated by calling the static 067 * <code>getInstance(String serviceName)</code> method. The parameter 068 * <code>serviceName</code> specifies the name of the service as mentioned in 069 * the XML file at the time of service registration. 070 * <p> 071 * Alternatively services and application can instantiate <code>I18n</code> 072 * object by specifying the resource bundle name (i.e., properties file name). 073 * Using this technique it is not possible to customize at runtime either the 074 * resource bundle name or the URL of the jar file that contains the properties 075 * file name. It is assumed that the properties file is present in 076 * <code>CLASSPATH</code> 077 * 078 * @supported.api 079 */ 080public class I18n { 081 082 /* ASCII ISO */ 083 public static final String ASCII_CHARSET = "ISO-8859-1"; 084 085 /* Static varibale that holds all the I18n objects */ 086 private static Map i18nMap = new HashMap(); 087 088 // private static SSOToken userSSOToken = null; 089 090 /* Instance variable */ 091 private boolean initialized = false; 092 093 private String serviceName = null; 094 095 private String i18nFile = null; 096 097 private ClassLoader ucl = null; 098 099 private Map resourceBundles = new HashMap(); 100 101 /** 102 * This constructor takes the name of the component as an argument and it 103 * should match with name of the resource bundle 104 */ 105 protected I18n(String serviceName) { 106 this.serviceName = serviceName; 107 } 108 109 private void initialize() { 110 if (initialized) 111 return; 112 113 // %%% Hack to get around cyclic dependency on I18n 114 // and other components that call I18n 115 i18nFile = serviceName; 116 initialized = true; 117 } 118 119 /** 120 * Method to get an instance of I18n object that has been either previously 121 * created or to obtain a new instance if it does'nt exist 122 * 123 * @param serviceName 124 * name of the service for which messages must be 125 * internationalized 126 * @return I18n object 127 * @supported.api 128 */ 129 public static I18n getInstance(String serviceName) { 130 if (serviceName == null) 131 return (null); 132 133 I18n i18nobj = null; 134 synchronized (i18nMap) { 135 if ((i18nobj = (I18n) i18nMap.get(serviceName)) == null) { 136 i18nobj = new I18n(serviceName); 137 i18nMap.put(serviceName, i18nobj); 138 } 139 } 140 return (i18nobj); 141 } 142 143 /** 144 * Method to obtain Locale object given its string representation 145 * 146 * @param stringformat 147 * Locale in a string format 148 * @return Locale object 149 */ 150 public static java.util.Locale getLocale(String stringformat) { 151 if (stringformat == null) 152 return java.util.Locale.getDefault(); 153 154 StringTokenizer tk = new StringTokenizer(stringformat, "_"); 155 String lang = ""; 156 String country = ""; 157 String variant = ""; 158 if (tk.hasMoreTokens()) 159 lang = tk.nextToken(); 160 if (tk.hasMoreTokens()) 161 country = tk.nextToken(); 162 if (tk.hasMoreTokens()) 163 variant = tk.nextToken(); 164 return (new java.util.Locale(lang, country, variant)); 165 } 166 167 /** 168 * Returns the resource file name associated with the service 169 * 170 * @return Returns the the ResourceBundle name associated with the service 171 */ 172 public String getResBundleName() { 173 initialize(); 174 return i18nFile; 175 } 176 177 /* Gets the resource bundle */ 178 private synchronized ResourceBundle getResourceBundle(String stringformat) { 179 ResourceBundle bundle = (ResourceBundle) resourceBundles 180 .get(stringformat); 181 if (bundle == null) { 182 if (ucl != null) { 183 bundle = ResourceBundle.getBundle(i18nFile, 184 getLocale(stringformat), ucl); 185 } else { 186 bundle = ResourceBundle.getBundle(i18nFile, 187 getLocale(stringformat)); 188 } 189 if (initialized) 190 resourceBundles.put(stringformat, bundle); 191 } 192 return (bundle); 193 } 194 195 /* Get the default locale stored in config */ 196 private static String getDefaultLocale() { 197 String loc = "en_US"; 198 199 /* %%% Get the default locale stored in config - to be implemented */ 200 return (loc); 201 } 202 203 /** 204 * Method to obtain internationalized message from the 205 * resource bundle given the key and locale. 206 * 207 * @param key 208 * key string in the properties file 209 * @param locale 210 * locale in a string format 211 * @return returns internationalized message for the specified key 212 * @supported.api 213 */ 214 public String getString(String key, String locale) { 215 initialize(); 216 if (key == null) { 217 return null; 218 } 219 ResourceBundle bundle = getResourceBundle(locale); 220 return (bundle.getString(key)); 221 } 222 223 /** 224 * Method to obtain internationalized message from the 225 * resource bundle given the key. 226 * 227 * @param key 228 * Key string in the properties file 229 * @return Returns value to the specified key 230 * @supported.api 231 */ 232 public String getString(String key) { 233 initialize(); 234 if (key == null) { 235 return null; 236 } 237 ResourceBundle bundle = getResourceBundle(getDefaultLocale()); 238 return (bundle.getString(key)); 239 } 240 241 /** 242 * Method to obtain internationalized message from the 243 * resource bundle given the key, locale and parameters. 244 * 245 * @param key 246 * key string in the properties file 247 * @param locale 248 * locale in a string format 249 * @param params 250 * parameters to be applied to the message 251 * @return returns internationalized message for the specified key 252 * @supported.api 253 */ 254 public String getString(String key, String locale, Object[] params) { 255 initialize(); 256 if (key == null) 257 return (null); 258 return (MessageFormat.format(getString(key, locale), params)); 259 } 260 261 /** 262 * Method to obtain internationalized message from the 263 * resource bundle given the key and parameters. 264 * 265 * @param key 266 * Key string in the properties file 267 * @param params 268 * parameters to be applied to the message 269 * @return Returns value to the specified key 270 * @supported.api 271 */ 272 public String getString(String key, Object[] params) { 273 initialize(); 274 if (key == null) 275 return (null); 276 return (MessageFormat.format(getString(key), params)); 277 } 278 279 /** 280 * Decodes the string into specified charset 281 * 282 * @param s 283 * string to be decoded 284 * @param charset 285 * character set in which the string to be decoded 286 * @return Returns the decoded string 287 */ 288 public static String decodeCharset(String s, String charset) { 289 if (s == null) { 290 return null; 291 } 292 293 try { 294 byte buf[] = s.getBytes(ASCII_CHARSET); 295 return (new String(buf, 0, buf.length, charset)); 296 } catch (UnsupportedEncodingException uee) { 297 return s; 298 } 299 } 300 301 /** 302 * Checks whether the string is ascii or not 303 * 304 * @param s 305 * string to be checked 306 * @return true if the string is ascii, otherwise false 307 */ 308 public static boolean isAscii(String s) { 309 if (s == null) { 310 return true; 311 } 312 313 try { 314 if (!s.equals(new String(s.getBytes(ASCII_CHARSET), ASCII_CHARSET))) 315 { 316 return false; 317 } 318 } catch (java.io.UnsupportedEncodingException uee) { 319 return false; 320 } 321 return true; 322 } 323 324 private static String format(MessageFormat mf, Object o) { 325 String msg = mf.format(new Object[] { o }, new StringBuffer(), null) 326 .toString(); 327 return msg; 328 } 329 330 /** 331 * Formats the objects into specified message format. 332 * 333 * @param pattern 334 * pattern for which the message to be formatted 335 * @param j 336 * Object to be formatted & substituted 337 * @param l 338 * locale in a string format 339 * @return Returns the formatted message 340 */ 341 public static String format(String pattern, Long j, String l) { 342 MessageFormat mf = new MessageFormat(""); 343 mf.setLocale(getLocale(l)); 344 mf.applyPattern(pattern); 345 String msg = format(mf, j); 346 347 return msg; 348 } 349 350 /** 351 * Formats the objects into specified message format. 352 * 353 * @param pattern 354 * pattern for which the message to be formatted 355 * @param i 356 * Integer to be formatted & substituted 357 * @param l 358 * locale in a string format 359 * @return Returns the formatted message 360 */ 361 public static String format(String pattern, Integer i, String l) { 362 MessageFormat mf = new MessageFormat(""); 363 mf.setLocale(getLocale(l)); 364 mf.applyPattern(pattern); 365 String msg = format(mf, i); 366 367 return msg; 368 } 369 370 /** 371 * Formats the objects into specified message format 372 * 373 * @param pattern 374 * pattern for which the message to be formatted 375 * @param d 376 * date 377 * @param tz 378 * Timezone 379 * @param l 380 * locale in a string format 381 * @return Returns the formatted message 382 */ 383 public static String format(String pattern, Date d, TimeZone tz, String l) { 384 385 MessageFormat mf = new MessageFormat(""); 386 mf.setLocale(getLocale(l)); 387 mf.applyPattern(pattern); 388 ((DateFormat) mf.getFormats()[0]).setTimeZone(tz); 389 390 DateFormat df1 = ((DateFormat) mf.getFormats()[0]); 391 if (df1 != null) { 392 df1.setTimeZone(tz); 393 } 394 395 DateFormat df2 = ((DateFormat) mf.getFormats()[1]); 396 if (df2 != null) { 397 df2.setTimeZone(tz); 398 } 399 400 return format(mf, d); 401 } 402}
Copyright © 2010-2017, ForgeRock All Rights Reserved.