001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.admin; 029 import org.opends.messages.Message; 030 031 032 033 import java.text.MessageFormat; 034 import java.util.HashMap; 035 import java.util.Locale; 036 import java.util.Map; 037 import java.util.MissingResourceException; 038 import java.util.ResourceBundle; 039 040 041 042 /** 043 * A class for retrieving internationalized resource properties 044 * associated with a managed object definition. 045 * <p> 046 * I18N resource properties are not available for the 047 * {@link TopCfgDefn}. 048 */ 049 public final class ManagedObjectDefinitionI18NResource { 050 051 // Application-wide set of instances. 052 private static final Map<String, ManagedObjectDefinitionI18NResource> 053 INSTANCES = new HashMap<String, ManagedObjectDefinitionI18NResource>(); 054 055 056 057 /** 058 * Gets the internationalized resource instance which can be used to 059 * retrieve the localized descriptions for the managed objects and 060 * their associated properties and relations. 061 * 062 * @return Returns the I18N resource instance. 063 */ 064 public static ManagedObjectDefinitionI18NResource getInstance() { 065 return getInstance("admin.messages"); 066 } 067 068 069 070 /** 071 * Gets the internationalized resource instance for the named 072 * profile. 073 * 074 * @param profile 075 * The name of the profile. 076 * @return Returns the I18N resource instance for the named profile. 077 */ 078 public static ManagedObjectDefinitionI18NResource getInstanceForProfile( 079 String profile) { 080 return getInstance("admin.profiles." + profile); 081 } 082 083 084 085 // Get a resource instance creating it if necessary. 086 private synchronized static ManagedObjectDefinitionI18NResource getInstance( 087 String prefix) { 088 ManagedObjectDefinitionI18NResource instance = INSTANCES 089 .get(prefix); 090 091 if (instance == null) { 092 instance = new ManagedObjectDefinitionI18NResource(prefix); 093 INSTANCES.put(prefix, instance); 094 } 095 096 return instance; 097 } 098 099 100 101 // Mapping from definition to locale-based resource bundle. 102 private final Map<AbstractManagedObjectDefinition<?, ?>, 103 Map<Locale, ResourceBundle>> resources; 104 105 106 107 // The resource name prefix. 108 private final String prefix; 109 110 111 112 // Private constructor. 113 private ManagedObjectDefinitionI18NResource(String prefix) { 114 this.resources = new HashMap<AbstractManagedObjectDefinition<?, ?>, 115 Map<Locale, ResourceBundle>>(); 116 this.prefix = prefix; 117 } 118 119 120 121 /** 122 * Get the internationalized message associated with the specified 123 * key in the default locale. 124 * 125 * @param d 126 * The managed object definition. 127 * @param key 128 * The resource key. 129 * @return Returns the internationalized message associated with the 130 * specified key in the default locale. 131 * @throws MissingResourceException 132 * If the key was not found. 133 * @throws UnsupportedOperationException 134 * If the provided managed object definition was the 135 * {@link TopCfgDefn}. 136 */ 137 public Message getMessage(AbstractManagedObjectDefinition<?, ?> d, String key) 138 throws MissingResourceException, UnsupportedOperationException { 139 return getMessage(d, key, Locale.getDefault(), (String[]) null); 140 } 141 142 143 144 /** 145 * Get the internationalized message associated with the specified 146 * key and locale. 147 * 148 * @param d 149 * The managed object definition. 150 * @param key 151 * The resource key. 152 * @param locale 153 * The locale. 154 * @return Returns the internationalized message associated with the 155 * specified key and locale. 156 * @throws MissingResourceException 157 * If the key was not found. 158 * @throws UnsupportedOperationException 159 * If the provided managed object definition was the 160 * {@link TopCfgDefn}. 161 */ 162 public Message getMessage(AbstractManagedObjectDefinition<?, ?> d, 163 String key, Locale locale) throws MissingResourceException, 164 UnsupportedOperationException { 165 return getMessage(d, key, locale, (String[]) null); 166 } 167 168 169 170 /** 171 * Get the parameterized internationalized message associated with 172 * the specified key and locale. 173 * 174 * @param d 175 * The managed object definition. 176 * @param key 177 * The resource key. 178 * @param locale 179 * The locale. 180 * @param args 181 * Arguments that should be inserted into the retrieved 182 * message. 183 * @return Returns the internationalized message associated with the 184 * specified key and locale. 185 * @throws MissingResourceException 186 * If the key was not found. 187 * @throws UnsupportedOperationException 188 * If the provided managed object definition was the 189 * {@link TopCfgDefn}. 190 */ 191 public Message getMessage(AbstractManagedObjectDefinition<?, ?> d, 192 String key, Locale locale, String... args) 193 throws MissingResourceException, UnsupportedOperationException { 194 ResourceBundle resource = getResourceBundle(d, locale); 195 196 // TODO: use message framework directly 197 if (args == null) { 198 return Message.raw(resource.getString(key)); 199 } else { 200 MessageFormat mf = new MessageFormat(resource.getString(key)); 201 return Message.raw(mf.format(args)); 202 } 203 } 204 205 206 207 /** 208 * Get the parameterized internationalized message associated with 209 * the specified key in the default locale. 210 * 211 * @param d 212 * The managed object definition. 213 * @param key 214 * The resource key. 215 * @param args 216 * Arguments that should be inserted into the retrieved 217 * message. 218 * @return Returns the internationalized message associated with the 219 * specified key in the default locale. 220 * @throws MissingResourceException 221 * If the key was not found. 222 * @throws UnsupportedOperationException 223 * If the provided managed object definition was the 224 * {@link TopCfgDefn}. 225 */ 226 public Message getMessage(AbstractManagedObjectDefinition<?, ?> d, 227 String key, String... args) throws MissingResourceException, 228 UnsupportedOperationException { 229 return getMessage(d, key, Locale.getDefault(), args); 230 } 231 232 233 234 /** 235 * Forcefully removes any resource bundles associated with the 236 * provided definition and using the default locale. 237 * <p> 238 * This method is intended for internal testing only. 239 * 240 * @param d 241 * The managed object definition. 242 */ 243 synchronized void removeResourceBundle( 244 AbstractManagedObjectDefinition<?, ?> d) { 245 removeResourceBundle(d, Locale.getDefault()); 246 } 247 248 249 250 /** 251 * Forcefully removes any resource bundles associated with the 252 * provided definition and locale. 253 * <p> 254 * This method is intended for internal testing only. 255 * 256 * @param d 257 * The managed object definition. 258 * @param locale 259 * The locale. 260 */ 261 synchronized void removeResourceBundle( 262 AbstractManagedObjectDefinition<?, ?> d, Locale locale) { 263 // Get the locale resource mapping. 264 Map<Locale, ResourceBundle> map = resources.get(d); 265 if (map != null) { 266 map.remove(locale); 267 } 268 } 269 270 271 272 /** 273 * Forcefully adds the provided resource bundle to this I18N 274 * resource for the default locale. 275 * <p> 276 * This method is intended for internal testing only. 277 * 278 * @param d 279 * The managed object definition. 280 * @param resoureBundle 281 * The resource bundle to be used. 282 */ 283 synchronized void setResourceBundle(AbstractManagedObjectDefinition<?, ?> d, 284 ResourceBundle resoureBundle) { 285 setResourceBundle(d, Locale.getDefault(), resoureBundle); 286 } 287 288 289 290 /** 291 * Forcefully adds the provided resource bundle to this I18N 292 * resource. 293 * <p> 294 * This method is intended for internal testing only. 295 * 296 * @param d 297 * The managed object definition. 298 * @param locale 299 * The locale. 300 * @param resoureBundle 301 * The resource bundle to be used. 302 */ 303 synchronized void setResourceBundle(AbstractManagedObjectDefinition<?, ?> d, 304 Locale locale, ResourceBundle resoureBundle) { 305 // First get the locale-resource mapping, creating it if 306 // necessary. 307 Map<Locale, ResourceBundle> map = resources.get(d); 308 if (map == null) { 309 map = new HashMap<Locale, ResourceBundle>(); 310 resources.put(d, map); 311 } 312 313 // Add the resource bundle. 314 map.put(locale, resoureBundle); 315 } 316 317 318 319 // Retrieve the resource bundle associated with a managed object and 320 // locale, lazily loading it if necessary. 321 private synchronized ResourceBundle getResourceBundle( 322 AbstractManagedObjectDefinition<?, ?> d, Locale locale) 323 throws MissingResourceException, UnsupportedOperationException { 324 if (d.isTop()) { 325 throw new UnsupportedOperationException( 326 "I18n resources are not available for the " 327 + "Top configuration definition"); 328 } 329 330 // First get the locale-resource mapping, creating it if 331 // necessary. 332 Map<Locale, ResourceBundle> map = resources.get(d); 333 if (map == null) { 334 map = new HashMap<Locale, ResourceBundle>(); 335 resources.put(d, map); 336 } 337 338 // Now get the resource based on the locale, loading it if 339 // necessary. 340 ResourceBundle resourceBundle = map.get(locale); 341 if (resourceBundle == null) { 342 String baseName = prefix + "." + d.getClass().getName(); 343 resourceBundle = ResourceBundle.getBundle(baseName, locale, 344 ClassLoaderProvider.getInstance().getClassLoader()); 345 map.put(locale, resourceBundle); 346 } 347 348 return resourceBundle; 349 } 350 }