Path: blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/Resources.java
40948 views
/*1* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.jconsole;2627import java.awt.event.KeyEvent;28import java.lang.reflect.Field;29import java.lang.reflect.Modifier;30import java.text.MessageFormat;31import java.util.Collections;32import java.util.IdentityHashMap;33import java.util.Map;34import java.util.MissingResourceException;35import java.util.ResourceBundle;3637/**38* Toolkit that provides resource support for JConsole.39*/40public final class Resources {41private static Map<String, Integer> MNEMONIC_LOOKUP = Collections42.synchronizedMap(new IdentityHashMap<String, Integer>());4344private Resources() {45throw new AssertionError();46}4748/**49* Convenience method for {@link MessageFormat#format(String, Object...)}.50*51* @param pattern the pattern52* @param objects the arguments for the pattern53*54* @return a formatted string55*/56public static String format(String pattern, Object... arguments) {57return MessageFormat.format(pattern, arguments);58}5960/**61* Returns the mnemonic for a message.62*63* @param message the message64*65* @return the mnemonic <code>int</code>66*/67public static int getMnemonicInt(String message) {68Integer integer = MNEMONIC_LOOKUP.get(message);69if (integer != null) {70return integer.intValue();71}72return 0;73}7475/**76* Initializes all public static non-final fields in the given class with77* messages from a {@link ResourceBundle}.78*79* @param clazz the class containing the fields80*/81public static void initializeMessages(Class<?> clazz, String rbName) {82ResourceBundle rb = null;83try {84rb = ResourceBundle.getBundle(rbName);85} catch (MissingResourceException mre) {86// fall through, handled later87}88for (Field field : clazz.getFields()) {89if (isWritableField(field)) {90String key = field.getName();91String message = getMessage(rb, key);92int mnemonicInt = findMnemonicInt(message);93message = removeMnemonicAmpersand(message);94message = replaceWithPlatformLineFeed(message);95setFieldValue(field, message);96MNEMONIC_LOOKUP.put(message, mnemonicInt);97}98}99}100101private static boolean isWritableField(Field field) {102int modifiers = field.getModifiers();103return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)104&& !Modifier.isFinal(modifiers);105}106107/**108* Returns the message corresponding to the key in the bundle or a text109* describing it's missing.110*111* @param rb the resource bundle112* @param key the key113*114* @return the message115*/116private static String getMessage(ResourceBundle rb, String key) {117if (rb == null) {118return "missing resource bundle";119}120try {121return rb.getString(key);122} catch (MissingResourceException mre) {123return "missing message for key = \"" + key124+ "\" in resource bundle ";125}126}127128private static void setFieldValue(Field field, String value) {129try {130field.set(null, value);131} catch (IllegalArgumentException | IllegalAccessException e) {132throw new Error("Unable to access or set message for field " + field.getName());133}134}135136/**137* Returns a {@link String} where all <code>\n</code> in the <text> have138* been replaced with the line separator for the platform.139*140* @param text the to be replaced141*142* @return the replaced text143*/144private static String replaceWithPlatformLineFeed(String text) {145return text.replace("\n", System.getProperty("line.separator"));146}147148/**149* Removes the mnemonic identifier (<code>&</code>) from a string unless150* it's escaped by <code>&&</code> or placed at the end.151*152* @param message the message153*154* @return a message with the mnemonic identifier removed155*/156private static String removeMnemonicAmpersand(String message) {157StringBuilder s = new StringBuilder();158for (int i = 0; i < message.length(); i++) {159char current = message.charAt(i);160if (current != '&' || i == message.length() - 1161|| message.charAt(i + 1) == '&') {162s.append(current);163}164}165return s.toString();166}167168/**169* Finds the mnemonic character in a message.170*171* The mnemonic character is the first character followed by the first172* <code>&</code> that is not followed by another <code>&</code>.173*174* @return the mnemonic as an <code>int</code>, or <code>0</code> if it175* can't be found.176*/177private static int findMnemonicInt(String s) {178for (int i = 0; i < s.length() - 1; i++) {179if (s.charAt(i) == '&') {180if (s.charAt(i + 1) != '&') {181return lookupMnemonicInt(s.substring(i + 1, i + 2));182} else {183i++;184}185}186}187return 0;188}189190/**191* Lookups the mnemonic for a key in the {@link KeyEvent} class.192*193* @param c the character to lookup194*195* @return the mnemonic as an <code>int</code>, or <code>0</code> if it196* can't be found.197*/198private static int lookupMnemonicInt(String c) {199try {200return KeyEvent.class.getDeclaredField("VK_" + c.toUpperCase())201.getInt(null);202} catch (IllegalArgumentException | IllegalAccessException203| NoSuchFieldException | SecurityException e) {204// Missing VK is okay205return 0;206}207}208}209210211