001    package org.apache.taglibs.datetime;
002    
003    import java.text.DateFormatSymbols;
004    import java.text.SimpleDateFormat;
005    import java.util.Date;
006    import java.util.Locale;
007    import java.util.TimeZone;
008    
009    import javax.servlet.jsp.JspException;
010    import javax.servlet.jsp.JspTagException;
011    import javax.servlet.jsp.PageContext;
012    import javax.servlet.jsp.tagext.BodyContent;
013    import javax.servlet.jsp.tagext.BodyTagSupport;
014    
015    public final class FormatTag extends BodyTagSupport     {
016    
017        // format tag attributes
018    
019        // Optional attribute, use users locale if known when formatting date
020        private boolean locale_flag = false;
021        // Optional attribute, time pattern string to use when formatting date
022        private String pattern = null;
023        // Optional attribute, name of script variable to use as pattern
024        private String patternid = null;
025        // Optional attribute, timeZone script variable id to use when formatting date
026        private String timeZone_string;
027        // Optional attribute, date object from rtexprvalue
028        private Date date = null;
029        // Optional attribute, the default text if the tag body or date given is invalid/null
030        private String default_text = "Invalid Date";
031        // Optional attribute, the name of an attribute which contains the Locale
032        private String localeRef = null;
033        // Optional attribute, name of script variable to use as date symbols source
034        private String symbolsRef = null;
035    
036        // format tag invocation variables
037    
038        // The symbols object
039        private DateFormatSymbols symbols = null;
040        // The date to be formatted an output by tag
041        private Date output_date = null;
042    
043        /**
044         * Method called at start of tag, always returns EVAL_BODY_TAG
045         *
046         * @return EVAL_BODY_TAG
047         */
048        public final int doStartTag() throws JspException
049        {
050            output_date = date;
051            return EVAL_BODY_TAG;
052        }
053    
054        /**
055         * Method called at end of format tag body.
056         *
057         * @return SKIP_BODY
058         */
059        public final int doAfterBody() throws JspException
060        {
061            // Use the body of the tag as input for the date
062            BodyContent body = getBodyContent();
063            String s = body.getString().trim();  
064            // Clear the body since we will output only the formatted date
065            body.clearBody();
066            if( output_date == null ) {
067                long time;
068                try {
069                    time = Long.valueOf(s).longValue();
070                    output_date = new Date(time);
071                } catch(NumberFormatException nfe) {
072                }
073            }
074    
075            return SKIP_BODY;
076        }
077    
078        /**
079         * Method called at end of Tag
080         *
081         * @return EVAL_PAGE
082         */
083        public final int doEndTag() throws JspException
084        {
085            String date_formatted = default_text;
086    
087            if (output_date != null) {
088                // Get the pattern to use
089                SimpleDateFormat sdf;
090                String pat = pattern;
091    
092                if (pat == null && patternid != null) {
093                    Object attr = pageContext.findAttribute(patternid);
094                    if (attr != null)
095                        pat = attr.toString();
096                }
097    
098                if (pat == null) {
099                    sdf = new SimpleDateFormat();
100                    pat = sdf.toPattern();
101                }
102    
103                // Get a DateFormatSymbols
104                if (symbolsRef != null) {
105                    symbols = (DateFormatSymbols) pageContext.findAttribute(symbolsRef);
106                    if (symbols == null) {
107                        throw new JspException(
108                                "datetime format tag could not find dateFormatSymbols for symbolsRef \"" +
109                                symbolsRef + "\".");
110                    }
111                }
112    
113                // Get a SimpleDateFormat using locale if necessary
114                if (localeRef != null) {
115                    Locale locale = (Locale) pageContext.findAttribute(localeRef);
116                    if (locale == null) {
117                        throw new JspException(
118                                "datetime format tag could not find locale for localeRef \"" +
119                                localeRef + "\".");
120                    }
121    
122                    sdf = new SimpleDateFormat(pat, locale);
123                } else if (locale_flag) {
124                    sdf = new SimpleDateFormat(pat,
125                             pageContext.getRequest().getLocale());
126                } else if (symbols != null) {
127                    sdf = new SimpleDateFormat(pat,
128                            symbols);
129                } else {
130                    sdf = new SimpleDateFormat(pat);
131                }
132    
133                // See if there is a timeZone
134                if (timeZone_string != null) {
135                    TimeZone timeZone =
136                            (TimeZone) pageContext.getAttribute(timeZone_string,
137                                    PageContext.SESSION_SCOPE);
138                    if (timeZone == null) {
139                        throw new JspTagException("Datetime format tag timeZone " +
140                                "script variable \"" + timeZone_string +
141                                " \" does not exist");
142                    }
143                    sdf.setTimeZone(timeZone);
144                }
145    
146                // Format the date for display
147                date_formatted = sdf.format(output_date);
148            }
149    
150            try {
151                pageContext.getOut().write(date_formatted);
152            } catch (Exception e) {
153                throw new JspException("IO Error: " + e.getMessage());
154            }
155    
156            return EVAL_PAGE;
157        }
158    
159        public void release()
160        {
161            //railo.print.ln("release FormatTag");
162            super.release();
163            locale_flag = false;
164            pattern = null;
165            patternid = null;
166            date = null;
167            localeRef = null;
168            symbolsRef = null;
169            symbols = null;
170        }
171    
172        /**
173         * Locale flag, if set to true, format date
174         * for client's preferred locale if known.
175         *
176         * @param boolean use users locale, true or false
177         */
178        public final void setLocale(short flag)
179        { 
180            //locale_flag = flag; 
181        }
182    
183        /**
184         * Set the time zone to use when formatting date.
185         *
186         * Value must be the name of a <b>timeZone</b> tag script
187         * variable ID.
188         *
189         * @param String name of timeZone to use
190         */
191        public final void setTimeZone(String tz)
192        {
193            timeZone_string = tz;
194        }
195    
196        /**
197         * Set the pattern to use when formatting Date.
198         *
199         * @param String SimpleDateFormat style time pattern format string
200         */
201        public final void setPattern(String str)
202        {
203            pattern = str;
204        }
205    
206        /**
207         * Set the pattern to use when parsing Date using a script variable
208         * attribute.
209         * 
210         * @param String name of script variable attribute id
211         */
212        public final void setPatternId(String str)
213        {   
214            patternid = str;
215        }
216    
217        /**
218         * Set the date to use (overrides tag body) for formatting
219         *
220         * @param Date to use for formatting (could be null)
221         */
222        public final void setDate(Date date)
223        {
224            this.date = date;
225        }
226    
227        /**
228         * Set the default text if an invalid date or no tag body is given
229         *
230         * @param String to use as default text
231         */
232        public final void setDefault(String default_text)
233        {
234            this.default_text = default_text;
235        }
236    
237        /**
238         * Provides a key to search the page context for in order to get the
239         * java.util.Locale to use.
240         *
241         * @param String name of locale attribute to use
242         */
243        public void setLocaleRef(String value)
244        {
245            localeRef = value;
246        }
247    
248        /**
249         * Provides a key to search the page context for in order to get the
250         * java.text.DateFormatSymbols to use
251         *
252         * @param symbolsRef
253         */
254        public void setSymbolsRef(String symbolsRef) {
255            this.symbolsRef = symbolsRef;
256        }
257        
258    }