View Javadoc

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 }