KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > i18n > BundleTag


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.i18n;
18
19 import java.util.Locale JavaDoc;
20 import java.util.ResourceBundle JavaDoc;
21 import java.util.Enumeration JavaDoc;
22
23 import javax.servlet.ServletContext JavaDoc;
24
25 import javax.servlet.http.HttpSession JavaDoc;
26
27 import javax.servlet.jsp.JspException JavaDoc;
28 import javax.servlet.jsp.JspTagException JavaDoc;
29 import javax.servlet.jsp.PageContext JavaDoc;
30 import javax.servlet.jsp.tagext.Tag JavaDoc;
31 import javax.servlet.jsp.tagext.TagSupport JavaDoc;
32
33
34 /**
35  * This class implements an empty tag that allows you to use a resource
36  * bundle to internationalize content in a web page. If a specific locale
37  * is not provided, the user's locale (language and country) are determined
38  * based on the browser settings. The response content-type is automatically
39  * set based on the locale.<br>
40  * This tag must be used very early in the page, prior to any html output.
41  * <P>
42  * <H2>Examples</H2>
43  * <PRE>
44  * &lt;i18n:bundle basename="test"/&gt;
45  * etc...
46  * </PRE>
47  * <P>
48  *
49  * @author <a HREF="mailto:tdawson@wamnet.com">Tim Dawson</a>
50  */

51 public class BundleTag extends TagSupport JavaDoc
52 {
53     private String JavaDoc _baseName = null;
54     private String JavaDoc _localeAttribute = null;
55     private Locale JavaDoc _locale = null;
56     private boolean _changeResponseLocale = true;
57     private ResourceBundle JavaDoc _bundle = null;
58     private int _scope = PageContext.PAGE_SCOPE;
59     private boolean _debug = false;
60     
61     /**
62      * Sets the baseName of the bundle that the MessageTags will use when
63      * retrieving keys for this page.
64      */

65     public final void setBaseName(String JavaDoc value)
66     {
67         _baseName = value;
68     }
69
70     /**
71      * Set to true to enable debug logging.
72      */

73     public final void setDebug(boolean value)
74     {
75         _debug = value;
76     }
77       
78       /**
79        * Sets the locale of the bundle that the MessageTags will use when
80        * retrieving keys for this page.
81        */

82       public void setLocale(Locale JavaDoc value)
83       {
84           _locale = value;
85       }
86
87     /**
88      * Provides a key to search the page context for in order to get the
89      * locale of the bundle that the MessageTags will use when retrieving
90      * keys for this page.
91      * @deprecated
92      */

93     public void setLocaleAttribute(String JavaDoc value)
94     {
95         _localeAttribute = value;
96     }
97
98     /**
99      * Provides a key to search the page context for in order to get the
100      * locale of the bundle that the MessageTags will use when retrieving
101      * keys for this page.
102      */

103     public void setLocaleRef(String JavaDoc value)
104     {
105         _localeAttribute = value;
106     }
107
108     /**
109      * Sets the scope that the bundle will be available to message tags.
110      * By default page scope is used.
111      */

112     public void setScope(String JavaDoc value) throws JspException JavaDoc
113     {
114         if (value == null)
115             {
116             throw new JspTagException JavaDoc("i18n:bundle tag invalid scope attribute of null");
117             }
118         else if (value.toLowerCase().equals("application"))
119             {
120             _scope = PageContext.APPLICATION_SCOPE;
121             }
122         else if (value.toLowerCase().equals("session"))
123             {
124             _scope = PageContext.SESSION_SCOPE;
125             }
126         else if (value.toLowerCase().equals("request"))
127             {
128             _scope = PageContext.REQUEST_SCOPE;
129             }
130         else if (value.toLowerCase().equals("page"))
131             {
132             _scope = PageContext.PAGE_SCOPE;
133             }
134         else
135             {
136             throw new JspTagException JavaDoc("i18n:bundle tag invalid scope attribute=" + value);
137             }
138     }
139
140     /**
141      * Specifies whether or not the response locale should be changed to match
142      * the locale used by this tag.
143      */

144     public void setChangeResponseLocale(boolean value)
145     {
146         _changeResponseLocale = value;
147     }
148
149     public void release()
150     {
151         super.release();
152         _baseName = null;
153         _localeAttribute = null;
154         _locale = null;
155         _changeResponseLocale = true;
156         _bundle = null;
157         _scope = PageContext.PAGE_SCOPE;
158         _debug = false;
159     }
160
161     /**
162      * Get the bundle created by this bundle tag, used by nested tags.
163      *
164      * @return ResourceBundle bundle
165      */

166     protected final ResourceBundle JavaDoc getBundle()
167     {
168         return _bundle;
169     }
170
171     /**
172      * Locates and prepares a ResourceBundle for use within this request by
173      * message tags. The bundle is located as specified by the given bundle
174      * name and the user's browser locale settings. The first preferred
175      * locale available that matches at least on basis of language is
176      * used. If an exact match is found for both locale and country, it is used.
177      *
178      * Once a preferred locale has been determined for the given bundle name,
179      * the locale is cached in the user's session, so that the above computation
180      * can be avoided the next time the user requests a page with this bundle.
181      * (The entire bundle could be cached in the session, but large bundles would
182      * be problematic in servlet containers that serialize the session to provide
183      * clustering.)
184      */

185     private void findBundle() throws JspException JavaDoc
186     {
187         // the bundle name is required. if not provided, throw an exception
188
if (_baseName == null) {
189             throw new JspTagException JavaDoc(
190                 "i18n:bundle tag, a baseName attribute must be specified.");
191         }
192
193         // Add a local variable to keep _locale unchanged.
194
Locale JavaDoc locale = _locale;
195
196         // if locale not provided, but an attribute was, search for it
197
if (locale == null && _localeAttribute != null) {
198             locale = (Locale JavaDoc)pageContext.findAttribute(_localeAttribute);
199         }
200
201         // if we now have a locale, grab the resource bundle
202
ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
203         if (locale != null) {
204             _bundle = ResourceBundle.getBundle(_baseName,locale,cl);
205             if (_debug) {
206                 ServletContext JavaDoc sc = pageContext.getServletContext();
207                 sc.log("i18n:bundle tag debug: found locale " + locale);
208             }
209         }
210         
211         // attempt to load the bundle and compute the locale by looping through
212
// the browser's preferred locales; cache the final locale for future use
213
else {
214             Enumeration JavaDoc localeEnumerator = pageContext.getRequest().getLocales();
215             while (localeEnumerator.hasMoreElements()) {
216                 locale = (Locale JavaDoc)localeEnumerator.nextElement();
217
218                 if (_debug) {
219                     ServletContext JavaDoc sc = pageContext.getServletContext();
220                     sc.log("i18n:bundle tag debug: enumerating locale = " + locale);
221                 }
222                     
223                 // get a bundle and see whether it has a good locale
224
ResourceBundle JavaDoc test =
225                     ResourceBundle.getBundle(_baseName,locale,cl);
226                 String JavaDoc language = test.getLocale().getLanguage();
227                 String JavaDoc country = test.getLocale().getCountry();
228
229                 // if the requested locale isn't available, the above call will
230
// return a bundle with a locale for the same language, or will
231
// return the default locale, so we need to compare the locale
232
// of the bundle we got back with the one we asked for
233
if (test.getLocale().equals(locale)) {
234                     // exactly what we were looking for - stop here and use this
235
_bundle = test;
236                     break;
237                 } else if (locale.getLanguage().equals(language)) {
238                     // the language matches; see if the country matches as well
239
if (locale.getCountry().equals(country)) {
240                         // keep looking but this is a good option. it only gets
241
// better if the variant matches too! (note: we will only
242
// get to this statement if a variant has been provided)
243
_bundle = test;
244                         continue;
245                     } else {
246                         // if we don't already have a candidate, this is a good
247
// one otherwise, don't change it because the current
248
// candidate might match the country but not the variant
249
if (_bundle == null) {
250                              _bundle = test;
251                         }
252                         continue;
253                     }
254                 } else if (_debug) {
255                     ServletContext JavaDoc sc = pageContext.getServletContext();
256                     sc.log("i18n:bundle tag requested locale not available: " + locale);
257                 }
258             }
259
260             // bundle should never be null at this point - if the last locale on
261
// the list wasn't available, the default locale should have kicked
262
// in, but I like being safe, hence the code below.
263
if (_bundle == null) {
264                 _bundle = ResourceBundle.getBundle(_baseName);
265             }
266
267             if (_debug) {
268                 ServletContext JavaDoc sc = pageContext.getServletContext();
269                 sc.log("i18n:bundle tag debug: bundle (sensed locale) = " + _bundle);
270             }
271             
272             // if the localeAttribute was provided, but didn't have a value,
273
// go ahead and remember the value for next time
274
if (_localeAttribute != null) {
275                 HttpSession JavaDoc session = pageContext.getSession();
276                 session.setAttribute(_localeAttribute,_bundle.getLocale());
277             }
278         }
279
280     }
281
282     /**
283      * Called upon invocation of the tag. If an id is specified, sets the
284      * bundle into the page context.
285      */

286     public int doStartTag() throws JspException JavaDoc
287     {
288         // initialize internal member variables
289
_bundle = null;
290         findBundle();
291
292         if (_debug) {
293             ServletContext JavaDoc sc = pageContext.getServletContext();
294             sc.log("i18n:bundle tag debug: basename =" + _baseName);
295         }
296
297         // set the bundle as a variable in the page
298
if (this.getId() != null) {
299             pageContext.setAttribute(this.getId(),_bundle);
300         }
301
302         return EVAL_BODY_INCLUDE;
303     }
304
305     /**
306      * Sets the response locale if changeResponseLocale attribute is true
307      */

308     public int doEndTag() throws JspException JavaDoc
309     {
310         if (_changeResponseLocale) {
311             // set the locale for the response
312
Locale JavaDoc bundleLocale = _bundle.getLocale();
313             if ((bundleLocale != null) && !("".equals(bundleLocale.getLanguage()))) {
314                 pageContext.getResponse().setLocale(bundleLocale);
315             }
316         }
317
318         // cache the bundle for use by message tags within this request
319
ResourceHelper.setBundle(pageContext,_bundle,_scope);
320
321         return EVAL_PAGE;
322     }
323
324 }
325
Popular Tags