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.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: We should find a way to save loaded bundles in the state, because otherwise on the next request the bundle map
50   * will not be present before the render phase and value bindings that reference to the bundle will always log annoying
51   * "Variable 'xxx' could not be resolved" error messages.
52   * </p>
53   * 
54   * @author Manfred Geiler (latest modification by $Author$)
55   * @version $Revision$ $Date$
56   */
57  @JSFJspTag(name = "f:loadBundle", bodyContent = "empty")
58  public class LoadBundleTag extends TagSupport
59  {
60      private static final long serialVersionUID = -8892145684062838928L;
61  
62      private ValueExpression _basename;
63      private String _var;
64  
65      /**
66       * The base name of the resource bundle.
67       */
68      @JSFJspAttribute(className="javax.el.ValueExpression",
69              deferredValueType="java.lang.String")
70      public void setBasename(ValueExpression basename)
71      {
72          _basename = basename;
73      }
74  
75      /**
76       * The name of the variable in request scope that the resources are saved to. This must be a static value.
77       */
78      @JSFJspAttribute(required = true)
79      public void setVar(String var)
80      {
81          _var = var;
82      }
83  
84      @Override
85      public int doStartTag() throws JspException
86      {
87          if (null == _var)
88          {
89              throw new NullPointerException("LoadBundle: 'var' must not be null");
90          }
91  
92          FacesContext facesContext = FacesContext.getCurrentInstance();
93          if (facesContext == null)
94          {
95              throw new JspException("No faces context?!");
96          }
97  
98          UIViewRoot viewRoot = facesContext.getViewRoot();
99          if (viewRoot == null)
100         {
101             throw new JspException("No view root! LoadBundle must be nested inside <f:view> action.");
102         }
103 
104         Locale locale = viewRoot.getLocale();
105         if (locale == null)
106         {
107             locale = facesContext.getApplication().getDefaultLocale();
108         }
109 
110         String basename = null;
111         if (_basename != null)
112         {
113             if (_basename.isLiteralText())
114             {
115                 basename = _basename.getExpressionString();
116             }
117             else
118             {
119                 basename = (String)_basename.getValue(facesContext.getELContext());
120             }
121         }
122 
123         if (null == basename)
124         {
125             throw new NullPointerException("LoadBundle: 'basename' must not be null");
126         }
127 
128         ResourceBundle bundle;
129         try
130         {
131             bundle = ResourceBundle.getBundle(basename,
132                                               locale,
133                                               ClassUtils.getContextClassLoader());
134         }
135         catch (MissingResourceException e)
136         {
137             try
138             {
139                 bundle = ResourceBundle.getBundle(basename,
140                         locale,
141                         this.getClass().getClassLoader());
142             }
143             catch (MissingResourceException e1)
144             {
145                 throw new JspException("Resource bundle '" + basename + "' could not be found.", e1);
146             }
147         }
148 
149         facesContext.getExternalContext().getRequestMap().put(_var, new BundleMap(bundle));
150         return Tag.SKIP_BODY;
151     }
152 
153     private static class BundleMap implements Map<String, String>
154     {
155         private ResourceBundle _bundle;
156         private List<String> _values;
157 
158         public BundleMap(ResourceBundle bundle)
159         {
160             _bundle = bundle;
161         }
162 
163         // Optimized methods
164 
165         public String get(Object key)
166         {
167             try
168             {
169                 return (String)_bundle.getObject(key.toString());
170             }
171             catch (Exception e)
172             {
173                 return "???" + key + "???";
174             }
175         }
176 
177         public boolean isEmpty()
178         {
179             return !_bundle.getKeys().hasMoreElements();
180         }
181 
182         public boolean containsKey(Object key)
183         {
184             try
185             {
186                 return _bundle.getObject(key.toString()) != null;
187             }
188             catch (MissingResourceException e)
189             {
190                 return false;
191             }
192         }
193 
194         // Unoptimized methods
195 
196         public Collection<String> values()
197         {
198             if (_values == null)
199             {
200                 _values = new ArrayList<String>();
201                 for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements();)
202                 {
203                     String v = _bundle.getString(enumer.nextElement());
204                     _values.add(v);
205                 }
206             }
207             return _values;
208         }
209 
210         public int size()
211         {
212             return values().size();
213         }
214 
215         public boolean containsValue(Object value)
216         {
217             return values().contains(value);
218         }
219 
220         public Set<Map.Entry<String, String>> entrySet()
221         {
222             Set<Entry<String, String>> set = new HashSet<Entry<String, String>>();
223             for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements();)
224             {
225                 final String k = enumer.nextElement();
226                 set.add(new Map.Entry<String, String>()
227                 {
228                     public String getKey()
229                     {
230                         return k;
231                     }
232 
233                     public String getValue()
234                     {
235                         return (String)_bundle.getObject(k);
236                     }
237 
238                     public String setValue(String value)
239                     {
240                         throw new UnsupportedOperationException(this.getClass().getName()
241                                 + " UnsupportedOperationException");
242                     }
243                 });
244             }
245             return set;
246         }
247 
248         public Set<String> keySet()
249         {
250             Set<String> set = new HashSet<String>();
251             for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements();)
252             {
253                 set.add(enumer.nextElement());
254             }
255             return set;
256         }
257 
258         // Unsupported methods
259 
260         public String remove(Object key)
261         {
262             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
263         }
264 
265         public void putAll(Map<? extends String, ? extends String> t)
266         {
267             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
268         }
269 
270         public String put(String key, String value)
271         {
272             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
273         }
274 
275         public void clear()
276         {
277             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
278         }
279 
280     }
281 
282 }