src/share/classes/sun/tools/jconsole/Resources.java

Print this page
rev 5340 : 7017818: NLS: JConsoleResources.java cannot be handled by translation team
Reviewed-by: duke


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.tools.jconsole;
  27 



  28 import java.text.MessageFormat;



  29 import java.util.MissingResourceException;
  30 import java.util.ResourceBundle;
  31 
  32 import sun.tools.jconsole.resources.JConsoleResources;
  33 
  34 /**
  35  * Provides resource support for jconsole.
  36  */
  37 public final class Resources {



































  38 
  39     private static final Object lock = new Object();
  40     private static JConsoleResources resources = null;
  41     static {






  42         try {
  43             resources =
  44                 (JConsoleResources)ResourceBundle.getBundle("sun.tools.jconsole.resources.JConsoleResources");
  45         } catch (MissingResourceException e) {
  46             // gracefully handle this later










  47         }
  48     }
  49 
  50     private Resources() { throw new AssertionError(); }




  51 
  52     /**
  53      * Returns the text of the jconsole resource for the specified key
  54      * formatted with the specified arguments.
  55      *





  56      */
  57     public static String getText(String key, Object... args) {
  58         String format = getString(key);
  59         if (format == null) {
  60             format = "missing resource key: key = \"" + key + "\", " +
  61                 "arguments = \"{0}\", \"{1}\", \"{2}\"";













  62         }
  63         return formatMessage(format, args);










  64     }
  65 
  66     static String formatMessage(String format, Object... args) {
  67         String ss = null;
  68         synchronized (lock) {
  69             /*
  70              * External synchronization required for safe use of
  71              * java.text.MessageFormat:


  72              */
  73             ss = MessageFormat.format(format, args);







  74         }
  75         return ss;
  76     }
  77 
  78     /**
  79      * Returns the mnemonic keycode int of the jconsole resource for the specified key.



  80      *


  81      */
  82     public static int getMnemonicInt(String key) {
  83         int mnemonic = 0;
  84         if (resources != null) {
  85             Object obj = resources.getObject(key+".mnemonic");
  86             if (obj instanceof Character) {
  87                 mnemonic = (int)(Character)obj;
  88                 if (mnemonic >= 'a' && mnemonic <='z') {
  89                     mnemonic -= ('a' - 'A');
  90                 }
  91             } else if (obj instanceof Integer) {
  92                 mnemonic = (Integer)obj;
  93             }
  94         }
  95         return mnemonic;
  96     }
  97 
  98     /**
  99      * Returns the jconsole resource string for the specified key.
 100      *





 101      */
 102     private static String getString(String key) {
 103         if (resources != null) {
 104             try {
 105                 return resources.getString(key);
 106             } catch (MissingResourceException e) {
 107                 return null;
 108             }


 109         }
 110         return "missing resource bundle: key = \"" + key + "\", " +
 111             "arguments = \"{0}\", \"{1}\", \"{2}\"";
 112     }
 113 }


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.tools.jconsole;
  27 
  28 import java.awt.event.KeyEvent;
  29 import java.lang.reflect.Field;
  30 import java.lang.reflect.Modifier;
  31 import java.text.MessageFormat;
  32 import java.util.Collections;
  33 import java.util.HashMap;
  34 import java.util.Map;
  35 import java.util.MissingResourceException;
  36 import java.util.ResourceBundle;
  37 


  38 /**
  39  * Toolkit that provides resource support for JConsole.
  40  */
  41 public final class Resources {
  42     private static Map<String, Integer> MNEMONIC_LOOKUP = Collections
  43             .synchronizedMap(new HashMap<String, Integer>());
  44 
  45     private Resources() {
  46         throw new AssertionError();
  47     }
  48 
  49     /**
  50      * Convenience method for {@link MessageFormat#format(String, Object...)}.
  51      *
  52      * @param pattern
  53      *            the pattern
  54      * @param objects
  55      *            the arguments for the pattern
  56      *
  57      * @return a formatted string
  58      */
  59     public static String format(String pattern, Object... arguments) {
  60             return MessageFormat.format(pattern, arguments);
  61     }
  62 
  63     /**
  64      * Returns the mnemonic for a message.
  65      *
  66      * @param message
  67      *
  68      * @return the mnemonic <code>int</code>
  69      */
  70     public static int getMnemonicInt(String message) {
  71         Integer integer = MNEMONIC_LOOKUP.get(message);
  72         if (integer != null) {
  73             return integer.intValue();
  74         }
  75         return 0;
  76     }
  77 
  78     /**
  79      * Initializes all non-final public static fields in the given class with
  80      * messages from a {@link ResourceBundle}.
  81      *
  82      * @param clazz
  83      *            the class containing the fields
  84      */
  85     public static void initializeMessages(Class<?> clazz, String rbName) {
  86         ResourceBundle rb = null;
  87         try {
  88             rb = ResourceBundle.getBundle(rbName);
  89         } catch (MissingResourceException mre) {
  90             // fall through, handled later
  91         }
  92         for (Field field : clazz.getFields()) {
  93             if (isWritableField(field)) {
  94                 String key = field.getName();
  95                 String message = getMessage(rb, key);
  96                 int mnemonicInt = findMnemonicInt(message);
  97                 message = removeMnemonicAmpersand(message);
  98                 message = replaceWithPlatformLineFeed(message);
  99                 setFieldValue(field, message);
 100                 MNEMONIC_LOOKUP.put(message, mnemonicInt);
 101             }
 102         }
 103     }
 104 
 105     private static boolean isWritableField(Field field) {
 106         int modifiers = field.getModifiers();
 107         return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
 108                 && !Modifier.isFinal(modifiers);
 109     }
 110 
 111     /**
 112      * Returns the message corresponding to the key in the bundle or a text
 113      * describing it's missing.
 114      *
 115      * @param rb
 116      *            the resource bundle
 117      * @param key
 118      *            the key
 119      * @return the message
 120      */
 121     private static String getMessage(ResourceBundle rb, String key) {
 122         if (rb == null) {
 123             return "missing resource bundle";
 124         }
 125         try {
 126             return rb.getString(key);
 127         } catch (MissingResourceException mre) {
 128             return "missing message for key = \"" + key
 129                     + "\" in resource bundle ";
 130         }
 131     }
 132 
 133     private static void setFieldValue(Field field, String value) {
 134         try {
 135             field.set(null, value);
 136         } catch (IllegalArgumentException | IllegalAccessException e) {
 137             // ignore
 138         }
 139     }
 140 
 141     /**
 142      * Returns a {@link String} where all <code>\n</code> in the <text> have
 143      * been replaced with the line separator for the platform.
 144      *
 145      * @param text
 146      *
 147      * @return the replaced text
 148      */
 149     private static String replaceWithPlatformLineFeed(String text) {
 150         return text.replace("\n", System.getProperty("line.separator"));
 151     }
 152 
 153     /**
 154      * Removes the mnemonic identifier (<code>&</code>) from a string unless
 155      * it's escaped by <code>&&</code> or placed at the end.
 156      *
 157      * @param message
 158      *            the message
 159      *
 160      * @return a message with the mnemonic identifier removed
 161      */
 162     private static String removeMnemonicAmpersand(String message) {
 163         StringBuilder s = new StringBuilder();
 164         for (int i = 0; i < message.length(); i++) {
 165             char current = message.charAt(i);
 166             if (current != '&' || i == message.length() - 1
 167                     || message.charAt(i + 1) == '&') {
 168                 s.append(current);
 169             }
 170         }
 171         return s.toString();
 172     }
 173 
 174     /**
 175      * Finds the mnemonic character in a message.
 176      *
 177      * The mnemonic character is the first character followed by the first
 178      * <code>&</code> that is not followed by another <code>&</code>.
 179      *
 180      * @return the mnemonic as an <code>int</code>, or <code>0</code> if it
 181      *         can't be found.
 182      */
 183     private static int findMnemonicInt(String s) {
 184         for (int i = 0; i < s.length() - 1; i++) {
 185             if (s.charAt(i) == '&') {
 186                 if (s.charAt(i + 1) != '&') {
 187                     return lookupMnemonicInt(s.substring(i + 1, i + 2));
 188                 } else {
 189                     i++;

 190                 }


 191             }
 192         }
 193         return 0;
 194     }
 195 
 196     /**
 197      * Lookups the mnemonic for a key in the {@link KeyEvent} class.
 198      *
 199      * @param c
 200      *            the character to lookup
 201      *
 202      * @return the mnemonic as an <code>int</code>, or <code>0</code> if it
 203      *         can't be found.
 204      */
 205     private static int lookupMnemonicInt(String c) {

 206         try {
 207             return KeyEvent.class.getDeclaredField("VK_" + c.toUpperCase())
 208                     .getInt(null);
 209         } catch (IllegalArgumentException | IllegalAccessException
 210                 | NoSuchFieldException | SecurityException e) {
 211             // Missing VK is okay
 212             return 0;
 213         }


 214     }
 215 }