1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.naming;
19
20 import java.text.MessageFormat;
21 import java.util.Hashtable;
22 import java.util.Locale;
23 import java.util.MissingResourceException;
24 import java.util.ResourceBundle;
25
26 /**
27 * An internationalization / localization helper class which reduces
28 * the bother of handling ResourceBundles and takes care of the
29 * common cases of message formating which otherwise require the
30 * creation of Object arrays and such.
31 *
32 * <p>The StringManager operates on a package basis. One StringManager
33 * per package can be created and accessed via the getManager method
34 * call.
35 *
36 * <p>The StringManager will look for a ResourceBundle named by
37 * the package name given plus the suffix of "LocalStrings". In
38 * practice, this means that the localized information will be contained
39 * in a LocalStrings.properties file located in the package
40 * directory of the classpath.
41 *
42 * <p>Please see the documentation for java.util.ResourceBundle for
43 * more information.
44 *
45 * @author James Duncan Davidson [duncan@eng.sun.com]
46 * @author James Todd [gonzo@eng.sun.com]
47 * @author Mel Martinez [mmartinez@g1440.com]
48 * @see java.util.ResourceBundle
49 */
50 public class StringManager {
51
52 /**
53 * The ResourceBundle for this StringManager.
54 */
55 private final ResourceBundle bundle;
56 private final Locale locale;
57
58 /**
59 * Creates a new StringManager for a given package. This is a
60 * private method and all access to it is arbitrated by the
61 * static getManager method call so that only one StringManager
62 * per package will be created.
63 *
64 * @param packageName Name of package to create StringManager for.
65 */
66 private StringManager(String packageName) {
67 String bundleName = packageName + ".LocalStrings";
68 ResourceBundle tempBundle = null;
69 try {
70 tempBundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
71 } catch( MissingResourceException ex ) {
72 // Try from the current loader (that's the case for trusted apps)
73 // Should only be required if using a TC5 style classloader structure
74 // where common != shared != server
75 ClassLoader cl = Thread.currentThread().getContextClassLoader();
76 if( cl != null ) {
77 try {
78 tempBundle = ResourceBundle.getBundle(
79 bundleName, Locale.getDefault(), cl);
80 } catch(MissingResourceException ex2) {
81 // Ignore
82 }
83 }
84 }
85 // Get the actual locale, which may be different from the requested one
86 if (tempBundle != null) {
87 locale = tempBundle.getLocale();
88 } else {
89 locale = null;
90 }
91 bundle = tempBundle;
92 }
93
94 /**
95 Get a string from the underlying resource bundle or return
96 null if the String is not found.
97
98 @param key to desired resource String
99 @return resource String matching <i>key</i> from underlying
100 bundle or null if not found.
101 @throws IllegalArgumentException if <i>key</i> is null.
102 */
103 public String getString(String key) {
104 if(key == null){
105 String msg = "key may not have a null value";
106
107 throw new IllegalArgumentException(msg);
108 }
109
110 String str = null;
111
112 try {
113 // Avoid NPE if bundle is null and treat it like an MRE
114 if (bundle != null) {
115 str = bundle.getString(key);
116 }
117 } catch(MissingResourceException mre) {
118 //bad: shouldn't mask an exception the following way:
119 // str = "[cannot find message associated with key '" + key + "' due to " + mre + "]";
120 // because it hides the fact that the String was missing
121 // from the calling code.
122 //good: could just throw the exception (or wrap it in another)
123 // but that would probably cause much havoc on existing
124 // code.
125 //better: consistent with container pattern to
126 // simply return null. Calling code can then do
127 // a null check.
128 str = null;
129 }
130
131 return str;
132 }
133
134 /**
135 * Get a string from the underlying resource bundle and format
136 * it with the given set of arguments.
137 *
138 * @param key The key for the required message
139 * @param args The values to insert into the message
140 *
141 * @return The request string formatted with the provided arguments or the
142 * key if the key was not found.
143 */
144 public String getString(final String key, final Object... args) {
145 String value = getString(key);
146 if (value == null) {
147 value = key;
148 }
149
150 MessageFormat mf = new MessageFormat(value);
151 mf.setLocale(locale);
152 return mf.format(args, new StringBuffer(), null).toString();
153 }
154
155 // --------------------------------------------------------------
156 // STATIC SUPPORT METHODS
157 // --------------------------------------------------------------
158
159 private static final Hashtable<String, StringManager> managers =
160 new Hashtable<>();
161
162 /**
163 * Get the StringManager for a particular package. If a manager for
164 * a package already exists, it will be reused, else a new
165 * StringManager will be created and returned.
166 *
167 * @param packageName The package name
168 *
169 * @return The instance associated with the given package
170 */
171 public static final synchronized StringManager getManager(String packageName) {
172 StringManager mgr = managers.get(packageName);
173 if (mgr == null) {
174 mgr = new StringManager(packageName);
175 managers.put(packageName, mgr);
176 }
177 return mgr;
178 }
179
180
181 public static final StringManager getManager(Class<?> clazz) {
182 return getManager(clazz.getPackage().getName());
183 }
184 }
185