View Javadoc

1   /*
2    * $Id: WriteTag.java 471754 2006-11-06 14:55:09Z husted $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.taglib.bean;
22  
23  import org.apache.struts.taglib.TagUtils;
24  import org.apache.struts.util.MessageResources;
25  
26  import javax.servlet.jsp.JspException;
27  import javax.servlet.jsp.tagext.TagSupport;
28  
29  import java.math.BigDecimal;
30  import java.math.BigInteger;
31  
32  import java.text.DecimalFormat;
33  import java.text.Format;
34  import java.text.NumberFormat;
35  import java.text.SimpleDateFormat;
36  
37  import java.util.Locale;
38  
39  /**
40   * Tag that retrieves the specified property of the specified bean, converts
41   * it to a String representation (if necessary), and writes it to the current
42   * output stream, optionally filtering characters that are sensitive in HTML.
43   *
44   * @version $Rev: 471754 $ $Date: 2004-10-16 12:38:42 -0400 (Sat, 16 Oct 2004)
45   *          $
46   */
47  public class WriteTag extends TagSupport {
48      /**
49       * The key to search default format string for java.sql.Timestamp in
50       * resources.
51       */
52      public static final String SQL_TIMESTAMP_FORMAT_KEY =
53          "org.apache.struts.taglib.bean.format.sql.timestamp";
54  
55      /**
56       * The key to search default format string for java.sql.Date in
57       * resources.
58       */
59      public static final String SQL_DATE_FORMAT_KEY =
60          "org.apache.struts.taglib.bean.format.sql.date";
61  
62      /**
63       * The key to search default format string for java.sql.Time in
64       * resources.
65       */
66      public static final String SQL_TIME_FORMAT_KEY =
67          "org.apache.struts.taglib.bean.format.sql.time";
68  
69      /**
70       * The key to search default format string for java.util.Date in
71       * resources.
72       */
73      public static final String DATE_FORMAT_KEY =
74          "org.apache.struts.taglib.bean.format.date";
75  
76      /**
77       * The key to search default format string for int (byte, short, etc.) in
78       * resources.
79       */
80      public static final String INT_FORMAT_KEY =
81          "org.apache.struts.taglib.bean.format.int";
82  
83      /**
84       * The key to search default format string for float (double, BigDecimal)
85       * in resources.
86       */
87      public static final String FLOAT_FORMAT_KEY =
88          "org.apache.struts.taglib.bean.format.float";
89  
90      /**
91       * The message resources for this package.
92       */
93      protected static MessageResources messages =
94          MessageResources.getMessageResources(
95              "org.apache.struts.taglib.bean.LocalStrings");
96  
97      // ------------------------------------------------------------- Properties
98  
99      /**
100      * Filter the rendered output for characters that are sensitive in HTML?
101      */
102     protected boolean filter = true;
103 
104     /**
105      * Should we ignore missing beans and simply output nothing?
106      */
107     protected boolean ignore = false;
108 
109     /**
110      * Name of the bean that contains the data we will be rendering.
111      */
112     protected String name = null;
113 
114     /**
115      * Name of the property to be accessed on the specified bean.
116      */
117     protected String property = null;
118 
119     /**
120      * The scope to be searched to retrieve the specified bean.
121      */
122     protected String scope = null;
123 
124     /**
125      * The format string to be used as format to convert value to String.
126      */
127     protected String formatStr = null;
128 
129     /**
130      * The key to search format string in applciation resources
131      */
132     protected String formatKey = null;
133 
134     /**
135      * The session scope key under which our Locale is stored.
136      */
137     protected String localeKey = null;
138 
139     /**
140      * The servlet context attribute key for our resources.
141      */
142     protected String bundle = null;
143 
144     public boolean getFilter() {
145         return (this.filter);
146     }
147 
148     public void setFilter(boolean filter) {
149         this.filter = filter;
150     }
151 
152     public boolean getIgnore() {
153         return (this.ignore);
154     }
155 
156     public void setIgnore(boolean ignore) {
157         this.ignore = ignore;
158     }
159 
160     public String getName() {
161         return (this.name);
162     }
163 
164     public void setName(String name) {
165         this.name = name;
166     }
167 
168     public String getProperty() {
169         return (this.property);
170     }
171 
172     public void setProperty(String property) {
173         this.property = property;
174     }
175 
176     public String getScope() {
177         return (this.scope);
178     }
179 
180     public void setScope(String scope) {
181         this.scope = scope;
182     }
183 
184     public String getFormat() {
185         return (this.formatStr);
186     }
187 
188     public void setFormat(String formatStr) {
189         this.formatStr = formatStr;
190     }
191 
192     public String getFormatKey() {
193         return (this.formatKey);
194     }
195 
196     public void setFormatKey(String formatKey) {
197         this.formatKey = formatKey;
198     }
199 
200     public String getLocale() {
201         return (this.localeKey);
202     }
203 
204     public void setLocale(String localeKey) {
205         this.localeKey = localeKey;
206     }
207 
208     public String getBundle() {
209         return (this.bundle);
210     }
211 
212     public void setBundle(String bundle) {
213         this.bundle = bundle;
214     }
215 
216     // --------------------------------------------------------- Public Methods
217 
218     /**
219      * Process the start tag.
220      *
221      * @throws JspException if a JSP exception has occurred
222      */
223     public int doStartTag() throws JspException {
224         // Look up the requested bean (if necessary)
225         if (ignore) {
226             if (TagUtils.getInstance().lookup(pageContext, name, scope)
227                 == null) {
228                 return (SKIP_BODY); // Nothing to output
229             }
230         }
231 
232         // Look up the requested property value
233         Object value =
234             TagUtils.getInstance().lookup(pageContext, name, property, scope);
235 
236         if (value == null) {
237             return (SKIP_BODY); // Nothing to output
238         }
239 
240         // Convert value to the String with some formatting
241         String output = formatValue(value);
242 
243         // Print this property value to our output writer, suitably filtered
244         if (filter) {
245             TagUtils.getInstance().write(pageContext,
246                 TagUtils.getInstance().filter(output));
247         } else {
248             TagUtils.getInstance().write(pageContext, output);
249         }
250 
251         // Continue processing this page
252         return (SKIP_BODY);
253     }
254 
255     /**
256      * Retrieve format string from message bundle and return null if message
257      * not found or message string.
258      *
259      * @param formatKey value to use as key to search message in bundle
260      * @throws JspException if a JSP exception has occurred
261      */
262     protected String retrieveFormatString(String formatKey)
263         throws JspException {
264         String result =
265             TagUtils.getInstance().message(pageContext, this.bundle,
266                 this.localeKey, formatKey);
267 
268         if ((result != null)
269             && !(result.startsWith("???") && result.endsWith("???"))) {
270             return result;
271         } else {
272             return null;
273         }
274     }
275 
276     /**
277      * Format value according to specified format string (as tag attribute or
278      * as string from message resources) or to current user locale.
279      *
280      * When a format string is retrieved from the message resources,
281      * <code>applyLocalizedPattern</code> is used. For more about localized
282      * patterns, see
283      * <http://www.dei.unipd.it/corsi/fi2ae-docs/source/jdk1.1.7/src/java/text/resources/>.
284      * (To obtain the correct value for some characters, you may need to view
285      * the file in a hex editor and then use the Unicode escape form in the
286      * property resources file.)
287      *
288      * @param valueToFormat value to process and convert to String
289      * @throws JspException if a JSP exception has occurred
290      */
291     protected String formatValue(Object valueToFormat)
292         throws JspException {
293         Format format = null;
294         Object value = valueToFormat;
295         Locale locale =
296             TagUtils.getInstance().getUserLocale(pageContext, this.localeKey);
297         boolean formatStrFromResources = false;
298         String formatString = formatStr;
299 
300         // Return String object as is.
301         if (value instanceof java.lang.String) {
302             return (String) value;
303         } else {
304             // Try to retrieve format string from resources by the key from
305             // formatKey.
306             if ((formatString == null) && (formatKey != null)) {
307                 formatString = retrieveFormatString(this.formatKey);
308 
309                 if (formatString != null) {
310                     formatStrFromResources = true;
311                 }
312             }
313 
314             // Prepare format object for numeric values.
315             if (value instanceof Number) {
316                 if (formatString == null) {
317                     if ((value instanceof Byte) || (value instanceof Short)
318                         || (value instanceof Integer)
319                         || (value instanceof Long)
320                         || (value instanceof BigInteger)) {
321                         formatString = retrieveFormatString(INT_FORMAT_KEY);
322                     } else if ((value instanceof Float)
323                         || (value instanceof Double)
324                         || (value instanceof BigDecimal)) {
325                         formatString = retrieveFormatString(FLOAT_FORMAT_KEY);
326                     }
327 
328                     if (formatString != null) {
329                         formatStrFromResources = true;
330                     }
331                 }
332 
333                 if (formatString != null) {
334                     try {
335                         format = NumberFormat.getNumberInstance(locale);
336 
337                         if (formatStrFromResources) {
338                             ((DecimalFormat) format).applyLocalizedPattern(
339                                 formatString);
340                         } else {
341                             ((DecimalFormat) format).applyPattern(formatString);
342                         }
343                     } catch (IllegalArgumentException e) {
344                         JspException ex =
345                             new JspException(messages.getMessage(
346                                     "write.format", formatString));
347 
348                         TagUtils.getInstance().saveException(pageContext, ex);
349                         throw ex;
350                     }
351                 }
352             } else if (value instanceof java.util.Date) {
353                 if (formatString == null) {
354                     if (value instanceof java.sql.Timestamp) {
355                         formatString =
356                             retrieveFormatString(SQL_TIMESTAMP_FORMAT_KEY);
357                     } else if (value instanceof java.sql.Date) {
358                         formatString =
359                             retrieveFormatString(SQL_DATE_FORMAT_KEY);
360                     } else if (value instanceof java.sql.Time) {
361                         formatString =
362                             retrieveFormatString(SQL_TIME_FORMAT_KEY);
363                     } else if (value instanceof java.util.Date) {
364                         formatString = retrieveFormatString(DATE_FORMAT_KEY);
365                     }
366                 }
367 
368                 if (formatString != null) {
369                     format = new SimpleDateFormat(formatString, locale);
370                 }
371             }
372         }
373 
374         if (format != null) {
375             return format.format(value);
376         } else {
377             return value.toString();
378         }
379     }
380 
381     /**
382      * Release all allocated resources.
383      */
384     public void release() {
385         super.release();
386         filter = true;
387         ignore = false;
388         name = null;
389         property = null;
390         scope = null;
391         formatStr = null;
392         formatKey = null;
393         localeKey = null;
394         bundle = null;
395     }
396 }