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.commons.resources.impl;
19
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.Locale;
23 import java.util.MissingResourceException;
24 import java.util.ResourceBundle;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.resources.ResourcesException;
29 import org.apache.commons.resources.ResourcesKeyException;
30 import org.apache.commons.resources.util.IteratorEnumeration;
31
32 /**
33 * <p>Concrete implementation of
34 * {@link org.apache.commons.resources.Resources} that wraps a set
35 * (one per Locale) of <code>java.util.ResourceBundle</code> instances
36 * that share a common base name.</p>
37 */
38 public class ResourceBundleResources extends ResourcesBase {
39
40 /**
41 * <p>The logging instance for this class.</p>
42 */
43 private transient Log log =
44 LogFactory.getLog(ResourceBundleResources.class);
45
46 // ----------------------------------------------------------- Constructors
47
48
49 /**
50 * <p>Create a new {@link org.apache.commons.resources.Resources}
51 * instance with the specified
52 * logical name and bundle base name.</p>
53 *
54 * @param name Logical name of the new instance
55 * @param base Fully qualified base name of the <code>ResourceBundle</code>
56 * instances to be wrapped
57 */
58 public ResourceBundleResources(String name, String base) {
59
60 super(name);
61 this.base = base;
62
63 }
64
65
66 // ----------------------------------------------------- Instance Variables
67
68
69 /**
70 * <p>The fully qualified base name of the <code>ResourceBundle</code>
71 * instances to be wrapped.</p>
72 */
73 private String base = null;
74
75
76 // ------------------------------------------------------------- Properties
77
78
79 /**
80 * <p>Return the fully qualified base name of the
81 * <code>ResourceBundle</code> instances we are wrapping.</p>
82 * @return The base name of this resources instance.
83 */
84 public String getBase() {
85
86 return (this.base);
87
88 }
89
90 /**
91 * <p>Return an <code>Iterator</code> over the defined keys in this
92 * {@link org.apache.commons.resources.Resources} instance.</p>
93 *
94 * @return The keys contained in this resources instance.
95 */
96 public Iterator getKeys() {
97
98 try {
99 ResourceBundle bundle = getBundle(null);
100 return new IteratorEnumeration(bundle.getKeys());
101
102 } catch (MissingResourceException e) {
103 return Collections.EMPTY_LIST.iterator();
104 }
105
106 }
107
108
109 // ---------------------------------------------- Content Retrieval Methods
110
111
112 /**
113 * <p>Return the content for the specified <code>key</code> as an
114 * Object, localized based on the specified <code>locale</code>.
115 * </p>
116 *
117 * @param key Identifier for the requested content
118 * @param locale Locale with which to localize retrieval,
119 * or <code>null</code> for the default Locale
120 * @return content for a specified key.
121 *
122 * @exception ResourcesException if an error occurs retrieving or
123 * returning the requested content
124 * @exception ResourcesKeyException if the no value for the specified
125 * key was found, and <code>isReturnNull()</code> returns
126 * <code>false</code>
127 */
128 public Object getObject(String key, Locale locale) {
129
130 if (getLog().isTraceEnabled()) {
131 getLog().trace("Retrieving message for key '" + key + "' and locale '"
132 + locale + "'");
133 }
134
135 try {
136 ResourceBundle bundle = getBundle(locale);
137 Object object = bundle.getObject(key);
138 if (getLog().isTraceEnabled()) {
139 getLog().trace("Retrieved object for key '" + key +
140 "' and locale '" + locale +
141 "' is '" + object + "'");
142 }
143 return object;
144
145 } catch (MissingResourceException e) {
146 if (getLog().isTraceEnabled()) {
147 getLog().trace("No resource found for key '" + key +
148 "' and locale '" + locale + "'");
149 }
150 if (isReturnNull()) {
151 return (null);
152 } else {
153 throw new ResourcesKeyException(key);
154 }
155 }
156
157 }
158
159
160 // ------------------------------------------------------ Protected Methods
161
162
163 /**
164 * <p>Return the appropriate <code>ResourceBundle</code> instance
165 * that corresponds to the specified <code>locale</code> parameter.
166 * The first time a particular bundle is requested, cache it so
167 * that subsequent requests will operate more quickly.</p>
168 *
169 * @param locale Locale with which to localize retrieval,
170 * or <code>null</code> for the default Locale
171 * @return The Resource Bundle corresponding to the locale and time zone.
172 *
173 * @exception MissingResourceException if the requested Resourcebundle
174 * cannot be acquired
175 */
176 protected ResourceBundle getBundle(Locale locale)
177 throws MissingResourceException {
178
179 if (locale == null) {
180 locale = Locale.getDefault();
181 }
182
183 // Locate the appropriate ClassLoader
184 ClassLoader loader = getClassLoader();
185
186 // Locate the requested ResourceBundle instance
187 ResourceBundle bundle = ResourceBundle.getBundle(base, locale, loader);
188
189 return (bundle);
190
191 }
192
193
194 /**
195 * <p>Return the <code>ClassLoader</code> for which we are mapping
196 * <code>ResourceBundle</code> instances.</p>
197 * @return The Class Loader for the resource bundle.
198 */
199 protected ClassLoader getClassLoader() {
200
201 ClassLoader loader = Thread.currentThread().getContextClassLoader();
202
203 if (loader == null) {
204 loader = this.getClass().getClassLoader();
205 }
206
207 return (loader);
208
209 }
210
211 /**
212 * Accessor method for Log instance.
213 *
214 * The Log instance variable is transient and
215 * accessing it through this method ensures it
216 * is re-initialized when this instance is
217 * de-serialized.
218 *
219 * @return The Log instance.
220 */
221 private Log getLog() {
222 if (log == null) {
223 log = LogFactory.getLog(ResourceBundleResources.class);
224 }
225 return log;
226 }
227
228 }