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