View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.taglib.core;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Enumeration;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.Map;
28  import java.util.MissingResourceException;
29  import java.util.ResourceBundle;
30  import java.util.Set;
31  
32  import javax.faces.component.UIViewRoot;
33  import javax.faces.context.FacesContext;
34  import javax.servlet.jsp.JspException;
35  import javax.servlet.jsp.tagext.Tag;
36  import javax.servlet.jsp.tagext.TagSupport;
37  import javax.el.ValueExpression;
38  
39  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspAttribute;
40  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspTag;
41  import org.apache.myfaces.shared_impl.util.ClassUtils;
42  
43  /**
44   * Loads a resource bundle and saves it as a variable in the request scope.
45   * <p>
46   * Unless otherwise specified, all attributes accept static values or EL expressions.
47   * </p>
48   * <p> 
49   * TODO:
50   * We should find a way to save loaded bundles in the state, because otherwise
51   * on the next request the bundle map will not be present before the render phase
52   * and value bindings that reference to the bundle will always log annoying
53   * "Variable 'xxx' could not be resolved" error messages.
54   * </p>
55   *
56   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
57   * @version $Revision: 924403 $ $Date: 2010-03-17 13:28:20 -0500 (Wed, 17 Mar 2010) $
58   */
59  @JSFJspTag(
60          name="f:loadBundle",
61          bodyContent="empty")
62  public class LoadBundleTag
63          extends TagSupport
64  {
65      private static final long serialVersionUID = -8892145684062838928L;
66  
67      private ValueExpression _basename;
68      private String _var;
69  
70      /**
71       * The base name of the resource bundle.
72       */
73      @JSFJspAttribute(
74              required=true,
75              rtexprvalue=true,
76              className="java.lang.String")
77      public void setBasename(ValueExpression basename)
78      {
79          _basename = basename;
80      }
81  
82      /**
83       * The name of the variable in request scope that the resources
84       * are saved to.  This must be a static value.
85       */
86      @JSFJspAttribute(required=true)
87      public void setVar(String var)
88      {
89          _var = var;
90      }
91  
92      public int doStartTag() throws JspException
93      {
94          if (null == _var)
95          {
96              throw new NullPointerException("LoadBundle: 'var' must not be null");
97          }
98  
99          FacesContext facesContext = FacesContext.getCurrentInstance();
100         if (facesContext == null)
101         {
102             throw new JspException("No faces context?!");
103         }
104 
105         UIViewRoot viewRoot = facesContext.getViewRoot();
106         if (viewRoot == null)
107         {
108             throw new JspException("No view root! LoadBundle must be nested inside <f:view> action.");
109         }
110 
111         Locale locale = viewRoot.getLocale();
112         if (locale == null)
113         {
114             locale = facesContext.getApplication().getDefaultLocale();
115         }
116 
117         String basename = null;
118         if (_basename!=null) {
119             if (_basename.isLiteralText()) {
120                 basename = _basename.getExpressionString();
121             } else {
122                 basename = (String) _basename.getValue(facesContext.getELContext());
123             }
124         }
125 
126         if (null == basename)
127         {
128             throw new NullPointerException("LoadBundle: 'basename' must not be null");
129         }
130 
131         ResourceBundle bundle;
132         try
133         {
134             bundle = ResourceBundle.getBundle(basename,
135                                               locale,
136                                               ClassUtils.getContextClassLoader());
137         }
138         catch (MissingResourceException e)
139         {
140             try
141             {
142                 bundle = ResourceBundle.getBundle(basename,
143                         locale,
144                         this.getClass().getClassLoader());
145             }
146             catch (MissingResourceException e1)
147             {
148                 throw new JspException("Resource bundle '" + basename + "' could not be found.", e1);
149             }
150         }
151 
152         facesContext.getExternalContext().getRequestMap().put(_var,
153                                                               new BundleMap(bundle));
154         return Tag.SKIP_BODY;
155     }
156 
157 
158     private static class BundleMap implements Map
159     {
160         private ResourceBundle _bundle;
161         private List<String> _values;
162 
163         public BundleMap(ResourceBundle bundle)
164         {
165             _bundle = bundle;
166         }
167 
168         //Optimized methods
169 
170         public Object get(Object key)
171         {
172             try {
173                 return _bundle.getObject(key.toString());
174             } catch (Exception e) {
175                 return "???" + key + "???";
176             }
177         }
178 
179         public boolean isEmpty()
180         {
181             return !_bundle.getKeys().hasMoreElements();
182         }
183 
184         public boolean containsKey(Object key)
185         {
186             try
187             {
188                 return _bundle.getObject(key.toString()) != null;
189             }
190             catch (MissingResourceException e)
191             {
192                 return false;
193             }
194         }
195 
196 
197         //Unoptimized methods
198 
199         public Collection values()
200         {
201             if (_values == null)
202             {
203                 _values = new ArrayList<String>();
204                 for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements();)
205                 {
206                     String v = _bundle.getString(enumer.nextElement());
207                     _values.add(v);
208                 }
209             }
210             return _values;
211         }
212 
213         public int size()
214         {
215             return values().size();
216         }
217 
218         public boolean containsValue(Object value)
219         {
220             return values().contains(value);
221         }
222 
223         public Set entrySet()
224         {
225             Set<Entry> set = new HashSet<Entry>();
226             for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements(); )
227             {
228                 final String k = enumer.nextElement();
229                 set.add(new Map.Entry() {
230                     public Object getKey()
231                     {
232                         return k;
233                     }
234 
235                     public Object getValue()
236                     {
237                         return _bundle.getObject(k);
238                     }
239 
240                     public Object setValue(Object value)
241                     {
242                         throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
243                     }
244                 });
245             }
246             return set;
247         }
248 
249         public Set keySet()
250         {
251             Set<String> set = new HashSet<String>();
252             for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements(); )
253             {
254                 set.add(enumer.nextElement());
255             }
256             return set;
257         }
258 
259 
260         //Unsupported methods
261 
262         public Object remove(Object key)
263         {
264             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
265         }
266 
267         public void putAll(Map t)
268         {
269             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
270         }
271 
272         public Object put(Object key, Object value)
273         {
274             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
275         }
276 
277         public void clear()
278         {
279             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
280         }
281 
282     }
283 
284 }