KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > standard > tag > common > fmt > BundleSupport


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.taglibs.standard.tag.common.fmt;
18
19 import java.io.IOException JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.Locale JavaDoc;
22 import java.util.MissingResourceException JavaDoc;
23 import java.util.ResourceBundle JavaDoc;
24
25 import javax.servlet.http.HttpServletRequest JavaDoc;
26 import javax.servlet.jsp.JspException JavaDoc;
27 import javax.servlet.jsp.JspTagException JavaDoc;
28 import javax.servlet.jsp.PageContext JavaDoc;
29 import javax.servlet.jsp.jstl.core.Config;
30 import javax.servlet.jsp.jstl.fmt.LocalizationContext;
31 import javax.servlet.jsp.tagext.BodyTagSupport JavaDoc;
32
33 import org.apache.taglibs.standard.tag.common.core.Util;
34
35 /**
36  * Support for tag handlers for <bundle>, the resource bundle loading
37  * tag in JSTL 1.0.
38  *
39  * @author Jan Luehe
40  */

41
42 public abstract class BundleSupport extends BodyTagSupport JavaDoc {
43     
44
45     //*********************************************************************
46
// Private constants
47

48     private static final Locale JavaDoc EMPTY_LOCALE = new Locale JavaDoc("", "");
49
50
51     //*********************************************************************
52
// Protected state
53

54     protected String JavaDoc basename; // 'basename' attribute
55
protected String JavaDoc prefix; // 'prefix' attribute
56

57
58     //*********************************************************************
59
// Private state
60

61     private Locale JavaDoc fallbackLocale;
62     private LocalizationContext locCtxt;
63
64
65     //*********************************************************************
66
// Constructor and initialization
67

68     public BundleSupport() {
69     super();
70     init();
71     }
72
73     private void init() {
74     basename = prefix = null;
75     locCtxt = null;
76     }
77
78     
79     //*********************************************************************
80
// Collaboration with subtags
81

82     public LocalizationContext getLocalizationContext() {
83     return locCtxt;
84     }
85
86     public String JavaDoc getPrefix() {
87     return prefix;
88     }
89
90
91     //*********************************************************************
92
// Tag logic
93

94     public int doStartTag() throws JspException JavaDoc {
95     locCtxt = getLocalizationContext(pageContext, basename);
96     return EVAL_BODY_BUFFERED;
97     }
98
99     public int doEndTag() throws JspException JavaDoc {
100     if (bodyContent != null) {
101         try {
102         pageContext.getOut().print(bodyContent.getString());
103         } catch (IOException JavaDoc ioe) {
104         throw new JspTagException JavaDoc(ioe.toString(), ioe);
105         }
106     }
107
108     return EVAL_PAGE;
109     }
110
111     // Releases any resources we may have (or inherit)
112
public void release() {
113     init();
114     }
115
116
117     //*********************************************************************
118
// Public utility methods
119

120     /**
121      * Gets the default I18N localization context.
122      *
123      * @param pc Page in which to look up the default I18N localization context
124      */

125     public static LocalizationContext getLocalizationContext(PageContext JavaDoc pc) {
126     LocalizationContext locCtxt = null;
127
128     Object JavaDoc obj = Config.find(pc, Config.FMT_LOCALIZATION_CONTEXT);
129     if (obj == null) {
130         return null;
131     }
132
133     if (obj instanceof LocalizationContext) {
134         locCtxt = (LocalizationContext) obj;
135     } else {
136         // localization context is a bundle basename
137
locCtxt = getLocalizationContext(pc, (String JavaDoc) obj);
138     }
139
140     return locCtxt;
141     }
142
143     /**
144      * Gets the resource bundle with the given base name, whose locale is
145      * determined as follows:
146      *
147      * Check if a match exists between the ordered set of preferred
148      * locales and the available locales, for the given base name.
149      * The set of preferred locales consists of a single locale
150      * (if the <tt>javax.servlet.jsp.jstl.fmt.locale</tt> configuration
151      * setting is present) or is equal to the client's preferred locales
152      * determined from the client's browser settings.
153      *
154      * <p> If no match was found in the previous step, check if a match
155      * exists between the fallback locale (given by the
156      * <tt>javax.servlet.jsp.jstl.fmt.fallbackLocale</tt> configuration
157      * setting) and the available locales, for the given base name.
158      *
159      * @param pageContext Page in which the resource bundle with the
160      * given base name is requested
161      * @param basename Resource bundle base name
162      *
163      * @return Localization context containing the resource bundle with the
164      * given base name and the locale that led to the resource bundle match,
165      * or the empty localization context if no resource bundle match was found
166      */

167     public static LocalizationContext getLocalizationContext(PageContext JavaDoc pc,
168                                  String JavaDoc basename) {
169     LocalizationContext locCtxt = null;
170     ResourceBundle JavaDoc bundle = null;
171
172     if ((basename == null) || basename.equals("")) {
173         return new LocalizationContext();
174     }
175
176     // Try preferred locales
177
Locale JavaDoc pref = SetLocaleSupport.getLocale(pc, Config.FMT_LOCALE);
178     if (pref != null) {
179         // Preferred locale is application-based
180
bundle = findMatch(basename, pref);
181         if (bundle != null) {
182         locCtxt = new LocalizationContext(bundle, pref);
183         }
184     } else {
185         // Preferred locales are browser-based
186
locCtxt = findMatch(pc, basename);
187     }
188     
189     if (locCtxt == null) {
190         // No match found with preferred locales, try using fallback locale
191
pref = SetLocaleSupport.getLocale(pc, Config.FMT_FALLBACK_LOCALE);
192         if (pref != null) {
193         bundle = findMatch(basename, pref);
194         if (bundle != null) {
195             locCtxt = new LocalizationContext(bundle, pref);
196         }
197         }
198     }
199
200     if (locCtxt == null) {
201         // try using the root resource bundle with the given basename
202
try {
203         bundle = ResourceBundle.getBundle(basename, EMPTY_LOCALE,
204                           Thread.currentThread().getContextClassLoader());
205         if (bundle != null) {
206             locCtxt = new LocalizationContext(bundle, null);
207         }
208         } catch (MissingResourceException JavaDoc mre) {
209         // do nothing
210
}
211     }
212          
213     if (locCtxt != null) {
214         // set response locale
215
if (locCtxt.getLocale() != null) {
216         SetLocaleSupport.setResponseLocale(pc, locCtxt.getLocale());
217         }
218     } else {
219         // create empty localization context
220
locCtxt = new LocalizationContext();
221     }
222
223     return locCtxt;
224     }
225
226
227     //*********************************************************************
228
// Private utility methods
229

230     /*
231      * Determines the client's preferred locales from the request, and compares
232      * each of the locales (in order of preference) against the available
233      * locales in order to determine the best matching locale.
234      *
235      * @param pageContext the page in which the resource bundle with the
236      * given base name is requested
237      * @param basename the resource bundle's base name
238      *
239      * @return the localization context containing the resource bundle with
240      * the given base name and best matching locale, or <tt>null</tt> if no
241      * resource bundle match was found
242      */

243     private static LocalizationContext findMatch(PageContext JavaDoc pageContext,
244                          String JavaDoc basename) {
245     LocalizationContext locCtxt = null;
246     
247     // Determine locale from client's browser settings.
248

249     for (Enumeration JavaDoc enum_ = Util.getRequestLocales((HttpServletRequest JavaDoc)pageContext.getRequest());
250          enum_.hasMoreElements(); ) {
251         Locale JavaDoc pref = (Locale JavaDoc) enum_.nextElement();
252         ResourceBundle JavaDoc match = findMatch(basename, pref);
253         if (match != null) {
254         locCtxt = new LocalizationContext(match, pref);
255         break;
256         }
257     }
258             
259     return locCtxt;
260     }
261
262     /*
263      * Gets the resource bundle with the given base name and preferred locale.
264      *
265      * This method calls java.util.ResourceBundle.getBundle(), but ignores
266      * its return value unless its locale represents an exact or language match
267      * with the given preferred locale.
268      *
269      * @param basename the resource bundle base name
270      * @param pref the preferred locale
271      *
272      * @return the requested resource bundle, or <tt>null</tt> if no resource
273      * bundle with the given base name exists or if there is no exact- or
274      * language-match between the preferred locale and the locale of
275      * the bundle returned by java.util.ResourceBundle.getBundle().
276      */

277     private static ResourceBundle JavaDoc findMatch(String JavaDoc basename, Locale JavaDoc pref) {
278     ResourceBundle JavaDoc match = null;
279
280     try {
281         ResourceBundle JavaDoc bundle =
282         ResourceBundle.getBundle(basename, pref,
283                      Thread.currentThread().getContextClassLoader());
284         Locale JavaDoc avail = bundle.getLocale();
285         if (pref.equals(avail)) {
286         // Exact match
287
match = bundle;
288         } else {
289                 /*
290                  * We have to make sure that the match we got is for
291                  * the specified locale. The way ResourceBundle.getBundle()
292                  * works, if a match is not found with (1) the specified locale,
293                  * it tries to match with (2) the current default locale as
294                  * returned by Locale.getDefault() or (3) the root resource
295                  * bundle (basename).
296                  * We must ignore any match that could have worked with (2) or (3).
297                  * So if an exact match is not found, we make the following extra
298                  * tests:
299                  * - avail locale must be equal to preferred locale
300                  * - avail country must be empty or equal to preferred country
301                  * (the equality match might have failed on the variant)
302          */

303                 if (pref.getLanguage().equals(avail.getLanguage())
304             && ("".equals(avail.getCountry()) || pref.getCountry().equals(avail.getCountry()))) {
305             /*
306              * Language match.
307              * By making sure the available locale does not have a
308              * country and matches the preferred locale's language, we
309              * rule out "matches" based on the container's default
310              * locale. For example, if the preferred locale is
311              * "en-US", the container's default locale is "en-UK", and
312              * there is a resource bundle (with the requested base
313              * name) available for "en-UK", ResourceBundle.getBundle()
314              * will return it, but even though its language matches
315              * that of the preferred locale, we must ignore it,
316              * because matches based on the container's default locale
317              * are not portable across different containers with
318              * different default locales.
319              */

320             match = bundle;
321         }
322         }
323     } catch (MissingResourceException JavaDoc mre) {
324     }
325
326     return match;
327     }
328 }
329
Popular Tags