001: /*
002: * $Id: WriteTag.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts.taglib.bean;
022:
023: import org.apache.struts.taglib.TagUtils;
024: import org.apache.struts.util.MessageResources;
025:
026: import javax.servlet.jsp.JspException;
027: import javax.servlet.jsp.tagext.TagSupport;
028:
029: import java.math.BigDecimal;
030: import java.math.BigInteger;
031:
032: import java.text.DecimalFormat;
033: import java.text.Format;
034: import java.text.NumberFormat;
035: import java.text.SimpleDateFormat;
036:
037: import java.util.Locale;
038:
039: /**
040: * Tag that retrieves the specified property of the specified bean, converts
041: * it to a String representation (if necessary), and writes it to the current
042: * output stream, optionally filtering characters that are sensitive in HTML.
043: *
044: * @version $Rev: 471754 $ $Date: 2004-10-16 12:38:42 -0400 (Sat, 16 Oct 2004)
045: * $
046: */
047: public class WriteTag extends TagSupport {
048: /**
049: * The key to search default format string for java.sql.Timestamp in
050: * resources.
051: */
052: public static final String SQL_TIMESTAMP_FORMAT_KEY = "org.apache.struts.taglib.bean.format.sql.timestamp";
053:
054: /**
055: * The key to search default format string for java.sql.Date in
056: * resources.
057: */
058: public static final String SQL_DATE_FORMAT_KEY = "org.apache.struts.taglib.bean.format.sql.date";
059:
060: /**
061: * The key to search default format string for java.sql.Time in
062: * resources.
063: */
064: public static final String SQL_TIME_FORMAT_KEY = "org.apache.struts.taglib.bean.format.sql.time";
065:
066: /**
067: * The key to search default format string for java.util.Date in
068: * resources.
069: */
070: public static final String DATE_FORMAT_KEY = "org.apache.struts.taglib.bean.format.date";
071:
072: /**
073: * The key to search default format string for int (byte, short, etc.) in
074: * resources.
075: */
076: public static final String INT_FORMAT_KEY = "org.apache.struts.taglib.bean.format.int";
077:
078: /**
079: * The key to search default format string for float (double, BigDecimal)
080: * in resources.
081: */
082: public static final String FLOAT_FORMAT_KEY = "org.apache.struts.taglib.bean.format.float";
083:
084: /**
085: * The message resources for this package.
086: */
087: protected static MessageResources messages = MessageResources
088: .getMessageResources("org.apache.struts.taglib.bean.LocalStrings");
089:
090: // ------------------------------------------------------------- Properties
091:
092: /**
093: * Filter the rendered output for characters that are sensitive in HTML?
094: */
095: protected boolean filter = true;
096:
097: /**
098: * Should we ignore missing beans and simply output nothing?
099: */
100: protected boolean ignore = false;
101:
102: /**
103: * Name of the bean that contains the data we will be rendering.
104: */
105: protected String name = null;
106:
107: /**
108: * Name of the property to be accessed on the specified bean.
109: */
110: protected String property = null;
111:
112: /**
113: * The scope to be searched to retrieve the specified bean.
114: */
115: protected String scope = null;
116:
117: /**
118: * The format string to be used as format to convert value to String.
119: */
120: protected String formatStr = null;
121:
122: /**
123: * The key to search format string in applciation resources
124: */
125: protected String formatKey = null;
126:
127: /**
128: * The session scope key under which our Locale is stored.
129: */
130: protected String localeKey = null;
131:
132: /**
133: * The servlet context attribute key for our resources.
134: */
135: protected String bundle = null;
136:
137: public boolean getFilter() {
138: return (this .filter);
139: }
140:
141: public void setFilter(boolean filter) {
142: this .filter = filter;
143: }
144:
145: public boolean getIgnore() {
146: return (this .ignore);
147: }
148:
149: public void setIgnore(boolean ignore) {
150: this .ignore = ignore;
151: }
152:
153: public String getName() {
154: return (this .name);
155: }
156:
157: public void setName(String name) {
158: this .name = name;
159: }
160:
161: public String getProperty() {
162: return (this .property);
163: }
164:
165: public void setProperty(String property) {
166: this .property = property;
167: }
168:
169: public String getScope() {
170: return (this .scope);
171: }
172:
173: public void setScope(String scope) {
174: this .scope = scope;
175: }
176:
177: public String getFormat() {
178: return (this .formatStr);
179: }
180:
181: public void setFormat(String formatStr) {
182: this .formatStr = formatStr;
183: }
184:
185: public String getFormatKey() {
186: return (this .formatKey);
187: }
188:
189: public void setFormatKey(String formatKey) {
190: this .formatKey = formatKey;
191: }
192:
193: public String getLocale() {
194: return (this .localeKey);
195: }
196:
197: public void setLocale(String localeKey) {
198: this .localeKey = localeKey;
199: }
200:
201: public String getBundle() {
202: return (this .bundle);
203: }
204:
205: public void setBundle(String bundle) {
206: this .bundle = bundle;
207: }
208:
209: // --------------------------------------------------------- Public Methods
210:
211: /**
212: * Process the start tag.
213: *
214: * @throws JspException if a JSP exception has occurred
215: */
216: public int doStartTag() throws JspException {
217: // Look up the requested bean (if necessary)
218: if (ignore) {
219: if (TagUtils.getInstance().lookup(pageContext, name, scope) == null) {
220: return (SKIP_BODY); // Nothing to output
221: }
222: }
223:
224: // Look up the requested property value
225: Object value = TagUtils.getInstance().lookup(pageContext, name,
226: property, scope);
227:
228: if (value == null) {
229: return (SKIP_BODY); // Nothing to output
230: }
231:
232: // Convert value to the String with some formatting
233: String output = formatValue(value);
234:
235: // Print this property value to our output writer, suitably filtered
236: if (filter) {
237: TagUtils.getInstance().write(pageContext,
238: TagUtils.getInstance().filter(output));
239: } else {
240: TagUtils.getInstance().write(pageContext, output);
241: }
242:
243: // Continue processing this page
244: return (SKIP_BODY);
245: }
246:
247: /**
248: * Retrieve format string from message bundle and return null if message
249: * not found or message string.
250: *
251: * @param formatKey value to use as key to search message in bundle
252: * @throws JspException if a JSP exception has occurred
253: */
254: protected String retrieveFormatString(String formatKey)
255: throws JspException {
256: String result = TagUtils.getInstance().message(pageContext,
257: this .bundle, this .localeKey, formatKey);
258:
259: if ((result != null)
260: && !(result.startsWith("???") && result.endsWith("???"))) {
261: return result;
262: } else {
263: return null;
264: }
265: }
266:
267: /**
268: * Format value according to specified format string (as tag attribute or
269: * as string from message resources) or to current user locale.
270: *
271: * When a format string is retrieved from the message resources,
272: * <code>applyLocalizedPattern</code> is used. For more about localized
273: * patterns, see
274: * <http://www.dei.unipd.it/corsi/fi2ae-docs/source/jdk1.1.7/src/java/text/resources/>.
275: * (To obtain the correct value for some characters, you may need to view
276: * the file in a hex editor and then use the Unicode escape form in the
277: * property resources file.)
278: *
279: * @param valueToFormat value to process and convert to String
280: * @throws JspException if a JSP exception has occurred
281: */
282: protected String formatValue(Object valueToFormat)
283: throws JspException {
284: Format format = null;
285: Object value = valueToFormat;
286: Locale locale = TagUtils.getInstance().getUserLocale(
287: pageContext, this .localeKey);
288: boolean formatStrFromResources = false;
289: String formatString = formatStr;
290:
291: // Return String object as is.
292: if (value instanceof java.lang.String) {
293: return (String) value;
294: } else {
295: // Try to retrieve format string from resources by the key from
296: // formatKey.
297: if ((formatString == null) && (formatKey != null)) {
298: formatString = retrieveFormatString(this .formatKey);
299:
300: if (formatString != null) {
301: formatStrFromResources = true;
302: }
303: }
304:
305: // Prepare format object for numeric values.
306: if (value instanceof Number) {
307: if (formatString == null) {
308: if ((value instanceof Byte)
309: || (value instanceof Short)
310: || (value instanceof Integer)
311: || (value instanceof Long)
312: || (value instanceof BigInteger)) {
313: formatString = retrieveFormatString(INT_FORMAT_KEY);
314: } else if ((value instanceof Float)
315: || (value instanceof Double)
316: || (value instanceof BigDecimal)) {
317: formatString = retrieveFormatString(FLOAT_FORMAT_KEY);
318: }
319:
320: if (formatString != null) {
321: formatStrFromResources = true;
322: }
323: }
324:
325: if (formatString != null) {
326: try {
327: format = NumberFormat.getNumberInstance(locale);
328:
329: if (formatStrFromResources) {
330: ((DecimalFormat) format)
331: .applyLocalizedPattern(formatString);
332: } else {
333: ((DecimalFormat) format)
334: .applyPattern(formatString);
335: }
336: } catch (IllegalArgumentException e) {
337: JspException ex = new JspException(messages
338: .getMessage("write.format",
339: formatString));
340:
341: TagUtils.getInstance().saveException(
342: pageContext, ex);
343: throw ex;
344: }
345: }
346: } else if (value instanceof java.util.Date) {
347: if (formatString == null) {
348: if (value instanceof java.sql.Timestamp) {
349: formatString = retrieveFormatString(SQL_TIMESTAMP_FORMAT_KEY);
350: } else if (value instanceof java.sql.Date) {
351: formatString = retrieveFormatString(SQL_DATE_FORMAT_KEY);
352: } else if (value instanceof java.sql.Time) {
353: formatString = retrieveFormatString(SQL_TIME_FORMAT_KEY);
354: } else if (value instanceof java.util.Date) {
355: formatString = retrieveFormatString(DATE_FORMAT_KEY);
356: }
357: }
358:
359: if (formatString != null) {
360: format = new SimpleDateFormat(formatString, locale);
361: }
362: }
363: }
364:
365: if (format != null) {
366: return format.format(value);
367: } else {
368: return value.toString();
369: }
370: }
371:
372: /**
373: * Release all allocated resources.
374: */
375: public void release() {
376: super .release();
377: filter = true;
378: ignore = false;
379: name = null;
380: property = null;
381: scope = null;
382: formatStr = null;
383: formatKey = null;
384: localeKey = null;
385: bundle = null;
386: }
387: }
|