KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > tags > databinding > bundle > DeclareBundle


1 /*
2  * Copyright 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  * $Header:$
17  */

18 package org.apache.beehive.netui.tags.databinding.bundle;
19
20 import javax.servlet.jsp.JspException JavaDoc;
21 import javax.servlet.jsp.tagext.TryCatchFinally JavaDoc;
22 import javax.servlet.http.HttpServletRequest JavaDoc;
23 import java.util.Locale JavaDoc;
24
25 import org.apache.beehive.netui.tags.AbstractClassicTag;
26 import org.apache.beehive.netui.util.Bundle;
27 import org.apache.beehive.netui.script.common.BundleMap;
28
29 /**
30  * <p>Declares a {@link java.util.ResourceBundle java.util.ResourceBundle} as a source for displaying internationalized
31  * messages. The declared resource bundle is accessible using the <code>${bundle...}</code> data binding context.
32  * The required <code>name</code> attribute specifies the identifier used to refer to the ResourceBundle in an expression.
33  * For example:
34  * <br/>
35  * <pre>
36  * &lt;netui-data:declareBundle name="someMessages" bundlePath="com/foobar/resources/WebAppMessages"/>
37  * </pre>
38  * <p>
39  * This tag declares a bundle that is referenced in a data binding expression as <code>${bundle.someMessages}</code>.
40  * </p>
41  * <p>
42  * The bundle that is referenced depends on the
43  * <a HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Locale.html" target="_blank">java.util.Locale</a>
44  * specified. The resource bundle properties files that are accessed are located
45  * in the package <code>com/foobar/resources</code> with the root properties file
46  * name of <code>WebAppMessages</code>. The naming conventions for properties can
47  * be found in Sun's Java documentation at
48  * <a HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)" target="_blank">ResourceBundle.getBundle(String,Locale, ClassLoader)</a> .
49  * These files must be located in a classpath that is available to the web application. Often, they are stored in
50  * <code>WEB-INF/classes</code>. If the properties file contains a key called <code>helloWorld</code>, then the
51  * expression <code>${bundle.someMessages.helloWorld}</code> would look-up the message
52  * matching the Locale specified on the tag. Bundle binding expressions can be
53  * used in any data bindable &lt;netui...> tag attribute.
54  * </p>
55  * <p>It is possible to have keys that contain multiple words separated by spaces, commas, or periods. If this is the
56  * case, then you must use slightly differente syntax to reference those keys in your data binding statement. The
57  * following list illustrates three ways to access the key <code>My helloWorld</code> from the
58  * <code>someMessages</code> property file:
59  * </p>
60  * <ul>
61  * <li><code>&lt;netui:span value=&quot;${bundle.someMessages['My helloWorld']}&quot;/&gt;</code></li>
62  * <li><code>&lt;netui:span value='${bundle.someMessages[&quot;My helloWorld&quot;]}'/&gt;</code></li>
63  * <li><code>&lt;netui:span value=&quot;${bundle.someMessages[\&quot;My helloWorld\&quot;]}&quot;/&gt;</code></li>
64  * </ul>
65  * <p>
66  * <b>Note:</b> the name <code>default</code> is a bundle identifier that is reserved for use by the
67  * &lt;netui-data:declareBundle> tag. If this value is used for the <code>name</code> attribute on a
68  * &lt;netui-data:declareBundle> tag, an error will be reported in the page. The <code>default</code> bundle
69  * is reserved for use when accessing internationalized messages from the "current" Struts module's
70  * default properties file.</p>
71  * <p/>
72  * <p>
73  * This tag provides a high level of customizability for rendering internationalized messages. Specifically, the
74  * {@link Locale} for which to look-up messages can be specified on the &lt;netui-data:declareBundle>
75  * tag. By default, the Locale for the current request is used, but this Locale can be overridden by
76  * setting the <code>language</code>, <code>country</code>, and <code>variant</code> tag attributes
77  * as necessary. See java.util.Locale for more information on the possible values for these attributes.</p>
78  * <p>The Locale can be overridden by setting these attributes in three combinations:</p>
79  * <blockquote>
80  * <ul>
81  * <li>country, language, variant</li>
82  * <li>country, language</li>
83  * <li>country</li>
84  * </ul>
85  * </blockquote>
86  * Any other combinations will throw an exception.
87  * </p>
88  * <p>The &lt;netui-data:declareBundle> tag and the Struts &lt;i18n:getMessage> tags have the following differences.
89  * The &lt;netui-data:declareBundle> tag lets you customize the use of a particular resource bundle with attributes
90  * to set the country, language, and variant explicitly, but it does not write a message out to the JSP page.
91  * Writing out a message from this bundle is done inside of any of the other tags using the <code>bundle</code>
92  * JSP EL implicit object.
93  * <p/>
94  * <pre>
95  * &lt;netui:span value="<b>${bundle.messages.messageKey}</b>"/>
96  * </pre>
97  * <p/>
98  * <p>The Struts &lt;i18n:getMessage> tag is used to access a bundle <i>and</i> write the message out. It
99  * is roughly equivalent to doing the following:
100  * <p/>
101  * <pre>
102  * &lt;netui-data:declareBundle bundlePath="com/foobar/resources/messages" name="messages"/>
103  * &lt;netui:span value="${bundle.messages.messageKey}"/></pre>
104  * <p/>
105  * <p>An advantage of using the ${bundle...} data binding context, is that it lets you write into the
106  * &lt;span>...&lt;/span> that the &lt;netui:span> creates, or into a &lt;neuti:checkBox> name, etc.
107  * just like using a regular String.
108  *
109  * @jsptagref.tagdescription
110  * <p>Declares a {@link java.util.ResourceBundle java.util.ResourceBundle} as a source for displaying internationalized
111  * messages. The declared resource bundle is accessible using the <code>${bundle...}</code> data binding context.
112  * The required <code>name</code> attribute specifies the identifier used to refer to the ResourceBundle in an expression.
113  * For example:
114  * <br/>
115  * <pre>
116  * &lt;netui-data:declareBundle name="someMessages" bundlePath="com/foobar/resources/WebAppMessages"/>
117  * </pre>
118  * <p>
119  * This tag declares a bundle that is referenced in a data binding expression as <code>${bundle.someMessages}</code>.
120  * </p>
121  * <p>
122  * The bundle that is referenced depends on the
123  * <a HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Locale.html" target="_blank">java.util.Locale</a>
124  * specified. The resource bundle properties files that are accessed are located
125  * in the package <code>com/foobar/resources</code> with the root properties file
126  * name of <code>WebAppMessages</code>. The naming conventions for properties can
127  * be found in Sun's Java documentation at
128  * <a HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)" target="_blank">ResourceBundle.getBundle(String,Locale, ClassLoader)</a> .
129  * These files must be located in a classpath that is available to the web application. Often, they are stored in
130  * <code>WEB-INF/classes</code>. If the properties file contains a key called <code>helloWorld</code>, then the
131  * expression <code>${bundle.someMessages.helloWorld}</code> would look-up the message
132  * matching the Locale specified on the tag. Bundle binding expressions can be
133  * used in any data bindable &lt;netui...> tag attribute.
134  * </p>
135  * <p>It is possible to have keys that contain multiple words separated by spaces,
136  * commas, or periods. If this is the case, then you must use slightly different
137  * syntax to reference those keys in your data binding statement. The following
138  * list illustrates three ways to access the key <code>My helloWorld</code> from the <code>someMessages</code>
139  * property file:
140  * </p>
141  * <ul>
142  * <li><code>&lt;netui:span value=&quot;${bundle.someMessages['My helloWorld']}&quot;/&gt;</code></li>
143  * <li><code>&lt;netui:span value='${bundle.someMessages[&quot;My helloWorld&quot;]}'/&gt;</code></li>
144  * <li><code>&lt;netui:span value=&quot;${bundle.someMessages[\&quot;My helloWorld\&quot;]}&quot;/&gt;</code></li>
145  * </ul>
146  * <p>
147  * <b>Note:</b> the name <code>default</code> is a bundle identifier that is reserved for use by the
148  * &lt;netui-data:declareBundle> tag. If this value is used for the <code>name</code> attribute on a
149  * &lt;netui-data:declareBundle> tag,
150  * an error will be reported in the page. The <code>default</code> bundle is reserved for use when
151  * accessing internationalized messages from the "current" Struts module's default properties file.</p>
152  * <p/>
153  * <p>
154  * This tag provides a high level of customizability for rendering internationalized messages.
155  * Specifically, the Locale for which to look-up messages can be specified on the
156  * &lt;netui-data:declareBundle>
157  * tag. By default, the Locale for the current request is used, but this Locale can be overridden by
158  * setting the <code>language</code>, <code>country</code>, and <code>variant</code> tag attributes
159  * as necessary. See java.util.Locale for more information on the possible values for these attributes.</p>
160  * <p>The Locale can be overridden by setting these attributes in three combinations:</p>
161  * <blockquote>
162  * <ul>
163  * <li>country, language, variant</li>
164  * <li>country, language</li>
165  * <li>country</li>
166  * </ul>
167  * </blockquote>
168  * Any other combinations will throw an exception.
169  * </p>
170  * <p>The &lt;netui-data:declareBundle> tag and the Struts &lt;i18n:getMessage> tags have the following differences.
171  * The &lt;netui-data:declareBundle> tag lets you customize the use of a particular resource bundle with attributes
172  * to set the country, language, and variant explicitly, but it does not write a message out to the JSP page.
173  * Writing out a message from this bundle is done inside of any of the other tags using the <code>bundle</code>
174  * JSP EL implicit object.
175  * <p/>
176  * <pre> &lt;netui:span value="<b>${bundle.messages.messageKey}</b>"/></pre>
177  * <p/>
178  * <p>The Struts &lt;i18n:getMessage> tag is used to access a bundle
179  * <i>and</i> write the message out. It is roughly equivalent to doing the following:
180  * <p/>
181  * <pre>
182  * &lt;netui-data:declareBundle bundlePath="com/foobar/resources/messages" name="messages"/>
183  * &lt;netui:span value="${bundle.messages.messageKey}"/></pre>
184  * <p/>
185  * <p>An advantage of using the ${bundle...} data binding context, is that it lets you write into the
186  * &lt;span>...&lt;/span> that the &lt;netui:span> creates, or into a &lt;neuti:checkBox> name, etc.
187  * just like using a regular String.
188  *
189  * @netui:tag name="declareBundle"
190  * description="Use this tag to declare a resource bundle that is available in the bundle databinding context"
191  */

192 public class DeclareBundle
193     extends AbstractClassicTag
194     implements TryCatchFinally JavaDoc {
195
196     private String JavaDoc _name = null;
197     private String JavaDoc _bundlePath = null;
198     private String JavaDoc _language = null;
199     private String JavaDoc _country = null;
200     private String JavaDoc _variant = null;
201
202     /**
203      * Get the name of this tag. This is used to identify the type of this tag
204      * for reporting tag errors.
205      *
206      * @return a constant String representing the name of this tag.
207      */

208     public String JavaDoc getTagName() {
209         return "DeclareBundle";
210     }
211
212     /**
213      * Set the language to use when looking-up resource bundle messages.
214      * The two-letter lowercase ISO-639 language code for the Locale from which to look-up resource bundle messages.
215      * This value is used to further specify the name of the .properties file from which message keys will be read.
216      *
217      * @param language the two-letter lowercase ISO-639 code for a language.
218      * @jsptagref.attributedescription
219      * Set the language to use when looking-up resource bundle messages.
220      * The two-letter lowercase ISO-639 language code for the Locale from which to look-up resource bundle messages.
221      * This value is used to further specify the name of the .properties file from which message keys will be read.
222      * @jsptagref.attributesyntaxvalue <i>string_language</i>
223      * @netui:attribute required="false" rtexprvalue="true"
224      */

225     public void setLanguage(String JavaDoc language) {
226         _language = language;
227     }
228
229     /**
230      * Set the country to use when looking-up resource bundle messages. The two-letter uppercase ISO-3166
231      * country / region code for the Locale from which to look-up resource bundle messages. This value is used to
232      * further specify the name of the .properties file from which message keys will be read.
233      *
234      * @param country the two-letter uppercase ISO-3166 code for a country
235      * @jsptagref.attributedescription
236      * Set the country to use when looking-up resource bundle messages. The two-letter uppercase ISO-3166
237      * country / region code for the Locale from which to look-up resource bundle messages. This value is used to
238      * further specify the name of the .properties file from which message keys will be read.
239      * @jsptagref.attributesyntaxvalue <i>string_country</i>
240      * @netui:attribute required="false" rtexprvalue="true"
241      */

242     public void setCountry(String JavaDoc country) {
243         _country = country;
244     }
245
246     /**
247      * Sets a vendor / browser specific code for further parameterizign the Locale from which to look-up resource bundle messages.
248      *
249      * @param variant the variant
250      * @jsptagref.attributedescription
251      * Sets a vendor / browser specific code for further parameterizign the Locale from which to look-up resource bundle messages.
252      * @jsptagref.attributesyntaxvalue <i>string_variant</i>
253      * @netui:attribute required="false" rtexprvalue="true"
254      */

255     public void setVariant(String JavaDoc variant) {
256         _variant = variant;
257     }
258
259     /**
260      * The name inside of the ${bundle...} databinding context under which the properties in this bundle are available.
261      * The identifier <code>default</code> is an illegal value for this attribute and is reserved for use by this tag.
262      *
263      * @param name the name of the bundle
264      * @jsptagref.attributedescription
265      * The name inside of the ${bundle...} databinding context under which the properties in this bundle are available.
266      * The identifier <code>default</code> is an illegal value for this attribute and is reserved for use by this tag.
267      * @jsptagref.attributesyntaxvalue <i>string_name</i>
268      * @netui:attribute required="true"
269      */

270     public void setName(String JavaDoc name) {
271         _name = name;
272     }
273
274     /**
275      * Set the path to the resource bundle's properties files. This can be a slash or dot delimited classpath.
276      * Valid values should appear as:
277      * <blockquote>
278      * <ul>
279      * <li>com/foobar/resources/WebAppProperties</li>
280      * <li>com.foobar.resources.WebAppProperties</li>
281      * </ul>
282      * </blockquote>
283      * <p>These are treated as equivalent values. The {@link java.util.ResourceBundle} class
284      * will handle appending the <code>.properties</code> file type and locale information
285      * as necessary. See {@link java.util.ResourceBundle#getBundle(String, Locale, ClassLoader)}
286      * for the <code>.properties</code> file naming conventions. These files must be available in
287      * classpath for the webapp in order to be successfully located.
288      *
289      * @param bundlePath the path to the bundle's properties files.
290      * @jsptagref.attributedescription
291      * Set the path to the resource bundle's properties files. This can be a slash or dot delimited classpath.
292      * Valid values should appear as:
293      * <blockquote>
294      * <ul>
295      * <li>com/foobar/resources/WebAppProperties</li>
296      * <li>com.foobar.resources.WebAppProperties</li>
297      * </ul>
298      * </blockquote>
299      * <p>These are treated as equivalent values. The {@link java.util.ResourceBundle} class
300      * will handle appending the <code>.properties</code> file type and locale information
301      * as necessary. See {@link java.util.ResourceBundle#getBundle(String, Locale, ClassLoader)}
302      * for the <code>.properties</code> file naming conventions. These files must be available in
303      * classpath for the webapp in order to be successfully located.
304      * @jsptagref.attributesyntaxvalue <i>string_bundlePath</i>
305      * @netui:attribute required="true"
306      */

307     public void setBundlePath(String JavaDoc bundlePath) {
308         _bundlePath = bundlePath;
309     }
310
311     /**
312      * Start the JSP rendering lifecycle for this tag; it skips its body.
313      *
314      * @return {@link #SKIP_BODY}
315      */

316     public int doStartTag() {
317         return SKIP_BODY;
318     }
319
320     /**
321      * Register a ResourceBundle that is available for the scope of this page. Errors raised
322      * during the execution of this tag will be reported in the page, which will continue
323      * rendering.
324      *
325      * @return {@link #EVAL_PAGE}
326      * @throws JspException if error conditions are encountered during this method which can not
327      * be reported in the page.
328      */

329     public int doEndTag()
330             throws JspException JavaDoc {
331
332         if(_name.length() == 0) {
333             String JavaDoc msg = Bundle.getErrorString("Tags_DeclareBundle_invalidName", new Object JavaDoc[]{_name});
334             registerTagError(msg, null);
335         }
336
337         if(_name.equals(BundleMap.DEFAULT_STRUTS_BUNDLE_NAME)) {
338             String JavaDoc msg = Bundle.getErrorString("Tags_DeclareBundle_defaultIsReservedWord", null);
339             registerTagError(msg, null);
340         }
341
342         if(_bundlePath.length() == 0) {
343             String JavaDoc msg = Bundle.getErrorString("Tags_DeclareBundle_invalidResourcePath", new Object JavaDoc[]{_bundlePath});
344             registerTagError(msg, null);
345         }
346
347         Locale JavaDoc locale = getCurrentLocale();
348
349         if(hasErrors()) {
350             reportErrors();
351             return EVAL_PAGE;
352         }
353
354         BundleMap bundleMap = null;
355         Object JavaDoc obj = pageContext.getAttribute("bundle");
356         if(obj == null) {
357             // NetUI v2 -- in JSP 2.0 EL, the BundleMap is dropped into the PageContext so that
358
// it's available to the EL runtime.
359
bundleMap = new BundleMap((HttpServletRequest JavaDoc)pageContext.getRequest(), pageContext.getServletContext());
360             pageContext.setAttribute("bundle", bundleMap);
361         }
362         else if(!(obj instanceof BundleMap)) {
363             String JavaDoc msg = Bundle.getErrorString("Tags_DeclareBundle_wrongContextType", new Object JavaDoc[]{obj.getClass().getName()});
364             registerTagError(msg, null);
365             if(hasErrors())
366                 reportErrors();
367             return EVAL_PAGE;
368         }
369         else
370             bundleMap = (BundleMap)obj;
371
372         bundleMap.registerResourceBundle(_name, _bundlePath, locale);
373
374         return EVAL_PAGE;
375     }
376
377     public void doFinally() {
378         localRelease();
379     }
380
381     public void doCatch(Throwable JavaDoc t)
382             throws Throwable JavaDoc {
383         throw t;
384     }
385
386     /**
387      * Reset all of the fields of this tag.
388      */

389     protected void localRelease() {
390         super.localRelease();
391         _name = null;
392         _bundlePath = null;
393         _language = null;
394         _country = null;
395         _variant = null;
396     }
397
398     private Locale JavaDoc getCurrentLocale()
399             throws JspException JavaDoc {
400         if(_language == null && _country == null && _variant == null)
401             return getUserLocale();
402
403         if(hasErrors())
404             return null;
405
406         if(_language != null && _country != null && _variant != null)
407             return new Locale JavaDoc(_language, _country, _variant);
408         else if(_language != null && _country != null)
409             return new Locale JavaDoc(_language, _country);
410         else if(_language != null)
411             return new Locale JavaDoc(_language);
412         else if(_country != null || _variant != null) {
413             String JavaDoc msg = Bundle.getErrorString("Tags_DeclareBundle_invalidLocaleOverride", new Object JavaDoc[]{_language, _country, _variant});
414             registerTagError(msg, null);
415         }
416
417         return getUserLocale();
418     }
419 }
420
Popular Tags