Index: test/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java =================================================================== --- test/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java (revision 0) +++ test/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java (revision 0) @@ -0,0 +1,44 @@ +/* + * Copyright 1999,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.taglibs.standard.tag.el.fmt; + +import javax.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class TestDateTag extends JspTestCase { + + public TestDateTag(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testDateTag() throws Exception { + String var = "varDate"; + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + String actual = (String) pageContext.getAttribute(var, PageContext.APPLICATION_SCOPE); + assertEquals("yyyy-MM-dd".length(), actual.length()); + } +} Property changes on: test/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java ___________________________________________________________________ Name: svn:eol-style + native Index: test/web/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp =================================================================== --- test/web/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp (revision 0) +++ test/web/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp (revision 0) @@ -0,0 +1,7 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + + Property changes on: test/web/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp ___________________________________________________________________ Name: svn:eol-style + native Index: src/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java (revision 580679) +++ src/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java (working copy) @@ -22,6 +22,8 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; +import java.util.Collections; +import java.util.Map; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; @@ -31,6 +33,8 @@ import org.apache.taglibs.standard.resources.Resources; import org.apache.taglibs.standard.tag.common.core.Util; +import org.apache.taglibs.standard.extra.commons.collections.map.LRUMap; + /** * Support for tag handlers for <formatDate>, the date and time * formatting tag in JSTL 1.0. @@ -43,11 +47,25 @@ //********************************************************************* // Private constants + /** + * Name of configuration setting for maximum number of entries in the + * cached dateformat map + */ + private static final String DATE_CACHE_PARAM = + "org.apache.taglibs.standard.tag.common.fmt.dateFormatCacheSize"; + private static final String DATE = "date"; private static final String TIME = "time"; private static final String DATETIME = "both"; + private static Map dateFormatCache = null; + /** + * Default maximum cache size + */ + private static final int MAX_SIZE = 100; + + //********************************************************************* // Protected state @@ -120,17 +138,8 @@ DateFormat.getAvailableLocales()); if (locale != null) { - DateFormat formatter = createFormatter(locale); + DateFormat formatter = createFormatter(locale, pattern); - // Apply pattern, if present - if (pattern != null) { - try { - ((SimpleDateFormat) formatter).applyPattern(pattern); - } catch (ClassCastException cce) { - formatter = new SimpleDateFormat(pattern, locale); - } - } - // Set time zone TimeZone tz = null; if ((timeZone instanceof String) @@ -180,22 +189,75 @@ //********************************************************************* // Private utility methods - private DateFormat createFormatter(Locale loc) throws JspException { + private DateFormat createFormatter(Locale loc, String pattern) throws JspException { DateFormat formatter = null; + // lazy initialization of cache + if (dateFormatCache == null) { + String value = pageContext.getServletContext().getInitParameter(DATE_CACHE_PARAM); + if (value != null) { + dateFormatCache = Collections.synchronizedMap(new LRUMap(Integer.parseInt(value))); + } else { + dateFormatCache = Collections.synchronizedMap(new LRUMap(MAX_SIZE)); + } + } + + // Apply pattern, if present + if (pattern != null) { + if ((type == null) || DATE.equalsIgnoreCase(type)) { + String key = DATE + pattern + loc; + formatter = (DateFormat) dateFormatCache.get(key); + if(formatter == null) { + formatter = new SimpleDateFormat(pattern, loc); + dateFormatCache.put(key, formatter); + } + } else if (TIME.equalsIgnoreCase(type)) { + String key = TIME + pattern + loc; + formatter = (DateFormat) dateFormatCache.get(key); + if(formatter == null) { + formatter = new SimpleDateFormat(pattern, loc); + dateFormatCache.put(key, formatter); + } + } else if (DATETIME.equalsIgnoreCase(type)) { + String key = DATETIME + pattern + loc; + formatter = (DateFormat) dateFormatCache.get(key); + if(formatter == null) { + formatter = new SimpleDateFormat(pattern, loc); + dateFormatCache.put(key, formatter); + } + } else { + throw new JspException( + Resources.getMessage("FORMAT_DATE_INVALID_TYPE", + type)); + } + return formatter; + } + if ((type == null) || DATE.equalsIgnoreCase(type)) { - formatter = DateFormat.getDateInstance( - Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"), - loc); + int style = Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"); + String key = DATE + style + loc; + formatter = (DateFormat) dateFormatCache.get(key); + if(formatter == null) { + formatter = DateFormat.getDateInstance(style, loc); + dateFormatCache.put(key, formatter); + } } else if (TIME.equalsIgnoreCase(type)) { - formatter = DateFormat.getTimeInstance( - Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"), - loc); + int style = Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"); + String key = TIME + style + loc; + formatter = (DateFormat) dateFormatCache.get(key); + if(formatter == null) { + formatter = DateFormat.getTimeInstance(style, loc); + dateFormatCache.put(key, formatter); + } } else if (DATETIME.equalsIgnoreCase(type)) { - formatter = DateFormat.getDateTimeInstance( - Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"), - Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"), - loc); + int style1 = Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"); + int style2 = Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"); + String key = DATETIME + style1 + loc + style2; + formatter = (DateFormat) dateFormatCache.get(key); + if(formatter == null) { + formatter = DateFormat.getDateTimeInstance(style1, style2, loc); + dateFormatCache.put(key, formatter); + } } else { throw new JspException( Resources.getMessage("FORMAT_DATE_INVALID_TYPE",