1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest.util; 28 29 import com.sun.javatest.ResourceLoader; 30 31 import java.security.AccessController; 32 import java.security.PrivilegedAction; 33 import java.text.MessageFormat; 34 import java.util.Enumeration; 35 import java.util.Locale; 36 import java.util.ResourceBundle; 37 import java.util.MissingResourceException; 38 39 /** 40 * A class that lazily opens a package-specific resource bundle 41 * containing localization data for a class. 42 */ 43 public class I18NResourceBundle extends ResourceBundle 44 { 45 /** 46 * Get a package-specific resource bundle for a class containing localization data. 47 * The bundle is named i18n.properties in the same 48 * package as the given class. 49 * @param c the class for which to obtain the resource bundle 50 * @return the appropriate resource bundle for the class 51 */ 52 public static I18NResourceBundle getBundleForClass(Class c) { 53 String cn = c.getName(); 54 int dot = cn.lastIndexOf('.'); 55 String rn = (dot == -1 ? "i18n" : cn.substring(0, dot) + ".i18n"); 56 boolean logging = (logClassPrefix == null ? false : cn.startsWith(logClassPrefix)); 57 return new I18NResourceBundle(rn, logging, c.getClassLoader()); 58 } 59 60 /** 61 * Get an entry from the resource bundle. 62 * If the resource cannot be found, a message is printed to the console 63 * and the result will be a string containing the method parameters. 64 * @param key the name of the entry to be returned 65 * @param arg an argument to be formatted into the result using 66 * {@link java.text.MessageFormat#format} 67 * @return the formatted string 68 */ 69 public String getString(String key, Object arg) { 70 return getString(key, new Object[] {arg}); 71 } 72 73 /** 74 * Get an entry from the resource bundle. 75 * If the resource cannot be found, a message is printed to the console 76 * and the result will be a string containing the method parameters. 77 * @param key the name of the entry to be returned 78 * @param args an array of arguments to be formatted into the result using 79 * {@link java.text.MessageFormat#format} 80 * @return the formatted string 81 */ 82 public String getString(String key, Object[] args) { 83 try { 84 return MessageFormat.format(getString(key), args); 85 } 86 catch (MissingResourceException e) { 87 System.err.println("WARNING: missing resource: " + key + " for " + name); 88 StringBuffer sb = new StringBuffer(key); 89 for (int i = 0; i < args.length; i++) { 90 sb.append('\n'); 91 sb.append(args[i].toString()); 92 } 93 return sb.toString(); 94 } 95 } 96 97 /** 98 * Get an entry from the bundle, returning null if it is not found. 99 * @param key the name of the entry to be returned 100 * @return the value of the entry, or null if it is not found. 101 */ 102 public String getOptionalString(String key) { 103 try { 104 String s = (String) getObj(key); 105 if (s != null && logging) { 106 System.out.println("i18n: " + key); 107 } 108 return s; 109 } 110 catch (MissingResourceException e) { 111 return null; 112 } 113 } 114 115 private Object getObj(String key) throws MissingResourceException { 116 try { 117 if (delegate == null) { 118 delegate = AccessController.doPrivileged( 119 new PrivilegedAction<ResourceBundle>() { 120 public ResourceBundle run() { 121 return ResourceLoader.getBundle(name, Locale.getDefault(), classLoader); 122 } 123 }); 124 } 125 return delegate.getObject(key); 126 } catch (MissingResourceException e) { 127 ResourceBundle bundle = AccessController.doPrivileged( 128 new PrivilegedAction<ResourceBundle>() { 129 public ResourceBundle run() { 130 return ResourceBundle.getBundle(name, Locale.getDefault(), classLoader); 131 } 132 }); 133 return bundle.getObject(key); 134 } 135 } 136 137 /** 138 * Create a resource bundle for the given name. 139 * The actual resource bundle will not be loaded until it is needed. 140 * @param name The name of the actual resource bundle to use. 141 */ 142 private I18NResourceBundle(String name, boolean logging, ClassLoader cl) { 143 this.name = name; 144 this.logging = logging; 145 this.classLoader = cl; 146 } 147 148 /** 149 * A required internal method for ResourceBundle. 150 * Load the actual resource bundle, if it has not yet been loaded, 151 * then hand the request off to that bundle. 152 * If the resource cannot be found, a message is printed to the console 153 * and the result will be the original key. 154 */ 155 protected Object handleGetObject(String key) throws MissingResourceException { 156 try { 157 if (logging) { 158 System.out.println("i18n: " + key); 159 } 160 return getObj(key); 161 } 162 catch (MissingResourceException e) { 163 System.err.println("WARNING: missing resource: " + key + " for " + name); 164 return key; 165 } 166 } 167 168 /** 169 * A required internal method for ResourceBundle. 170 * Load the actual resource bundle, if it has not yet been loaded, 171 * then hand the request off to that bundle. 172 */ 173 public Enumeration<String> getKeys() { 174 if (delegate == null) { 175 delegate = AccessController.doPrivileged( 176 new PrivilegedAction<ResourceBundle>() { 177 public ResourceBundle run() { 178 return ResourceLoader.getBundle(name, Locale.getDefault(), classLoader); 179 } 180 }); 181 182 } 183 if (delegate.getKeys().hasMoreElements()) { 184 return delegate.getKeys(); 185 } 186 187 ResourceBundle bundle = AccessController.doPrivileged( 188 new PrivilegedAction<ResourceBundle>() { 189 public ResourceBundle run() { 190 return ResourceBundle.getBundle(name, Locale.getDefault(), classLoader); 191 } 192 }); 193 return bundle.getKeys(); 194 } 195 196 /** 197 * Returns the name of this bundle (useful for methods using 198 * bundle name instead of instance, such as <code>Logger</code> creation, 199 * @return the name of this resource bundle 200 */ 201 202 public String getName() { 203 return name; 204 } 205 206 private String name; 207 private ResourceBundle delegate; 208 private boolean logging; 209 private ClassLoader classLoader; 210 private static final String logClassPrefix = System.getProperty("javatest.i18n.log"); 211 }