Index: src/org/apache/taglibs/standard/lang/jstl/Constants.java =================================================================== --- src/org/apache/taglibs/standard/lang/jstl/Constants.java (revision 504759) +++ src/org/apache/taglibs/standard/lang/jstl/Constants.java (working copy) @@ -33,6 +33,18 @@ public class Constants { //------------------------------------- + // SPI extensions + + public static final String ELEVALUATOR_EXPECTED_STRINGS_CACHE = + "org.apache.taglibs.standard.elevalutor.expected.strings.cache"; + public static final String ELEVALUATOR_EXPECTED_TYPES_CACHE = + "org.apache.taglibs.standard.elevalutor.expected.types.cache"; + public static final String MESSAGEFORMAT_CACHE = + "org.apache.taglibs.standard.messageformat.cache"; + public static final String DATEFORMAT_CACHE = + "org.apache.taglibs.standard.dateformat.cache"; + + //------------------------------------- // Resources static ResourceBundle sResources = Index: src/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java =================================================================== --- src/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java (revision 504759) +++ src/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java (working copy) @@ -28,6 +28,8 @@ import org.apache.taglibs.standard.lang.jstl.parser.Token; import org.apache.taglibs.standard.lang.jstl.parser.TokenMgrError; +import org.apache.taglibs.standard.util.*; + /** * *

This is the main class for evaluating expression Strings. An @@ -91,12 +93,19 @@ /** The mapping from expression String to its parsed form (String, Expression, or ExpressionString) **/ - static Map sCachedExpressionStrings = - Collections.synchronizedMap (new HashMap ()); + static StandardTaglibCache sCachedExpressionStrings = + StandardTaglibCacheFactory.createCache( + Constants.ELEVALUATOR_EXPECTED_STRINGS_CACHE, + ForeverStandardTaglibCache.class + ); /** The mapping from ExpectedType to Maps mapping literal String to parsed value **/ - static Map sCachedExpectedTypes = new HashMap (); + static StandardTaglibCache sCachedExpectedTypes = + StandardTaglibCacheFactory.createCache( + Constants.ELEVALUATOR_EXPECTED_TYPES_CACHE, + ForeverStandardTaglibCache.class + ); /** The static Logger **/ static Logger sLogger = new Logger (System.out); @@ -104,9 +113,6 @@ /** The VariableResolver **/ VariableResolver mResolver; - /** Flag if the cache should be bypassed **/ - boolean mBypassCache; - //------------------------------------- /** * @@ -124,25 +130,6 @@ //------------------------------------- /** * - * Constructor - * - * @param pResolver the object that should be used to resolve - * variable names encountered in expressions. If null, all variable - * references will resolve to null. - * - * @param pBypassCache flag indicating if the cache should be - * bypassed - **/ - public ELEvaluator (VariableResolver pResolver, - boolean pBypassCache) - { - mResolver = pResolver; - mBypassCache = pBypassCache; - } - - //------------------------------------- - /** - * * Evaluates the given expression String * * @param pExpressionString the expression String to be evaluated @@ -248,10 +235,7 @@ } // See if it's in the cache - Object ret = - mBypassCache ? - null : - sCachedExpressionStrings.get (pExpressionString); + Object ret = sCachedExpressionStrings.get (pExpressionString); if (ret == null) { // Parse the expression @@ -311,8 +295,7 @@ // Find the cached value Map valueByString = getOrCreateExpectedTypeMap (pExpectedType); - if (!mBypassCache && - valueByString.containsKey (pValue)) { + if (valueByString.containsKey (pValue)) { return valueByString.get (pValue); } else { @@ -331,14 +314,12 @@ **/ static Map getOrCreateExpectedTypeMap (Class pExpectedType) { - synchronized (sCachedExpectedTypes) { Map ret = (Map) sCachedExpectedTypes.get (pExpectedType); if (ret == null) { ret = Collections.synchronizedMap (new HashMap ()); sCachedExpectedTypes.put (pExpectedType, ret); } return ret; - } } //------------------------------------- Index: src/org/apache/taglibs/standard/resources/Resources.java =================================================================== --- src/org/apache/taglibs/standard/resources/Resources.java (revision 504759) +++ src/org/apache/taglibs/standard/resources/Resources.java (working copy) @@ -20,6 +20,9 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; +import org.apache.taglibs.standard.util.*; +import org.apache.taglibs.standard.lang.jstl.Constants; + /** *

Provides locale-neutral access to string resources. Only the * documentation and code are in English. :-) @@ -52,7 +55,10 @@ private static ResourceBundle rb = ResourceBundle.getBundle(RESOURCE_LOCATION); + private static StandardTaglibCache messageFormatCache = + StandardTaglibCacheFactory.createCache(Constants.MESSAGEFORMAT_CACHE); + //********************************************************************* // Public static methods @@ -66,7 +72,12 @@ public static String getMessage(String name, Object[] a) throws MissingResourceException { String res = rb.getString(name); - return MessageFormat.format(res, a); + MessageFormat msgFormat = (MessageFormat) messageFormatCache.get(res); + if(msgFormat == null) { + msgFormat = new MessageFormat(res); + messageFormatCache.put(res, msgFormat); + } + return msgFormat.format(res, a); } /** Retrieves a message with one argument. */ Index: src/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java (revision 504759) +++ src/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java (working copy) @@ -31,6 +31,9 @@ import org.apache.taglibs.standard.resources.Resources; import org.apache.taglibs.standard.tag.common.core.Util; +import org.apache.taglibs.standard.util.*; +import org.apache.taglibs.standard.lang.jstl.Constants; + /** * Support for tag handlers for <formatDate>, the date and time * formatting tag in JSTL 1.0. @@ -65,6 +68,8 @@ private String var; // 'var' attribute private int scope; // 'scope' attribute + private static StandardTaglibCache dateFormatCache = + StandardTaglibCacheFactory.createCache(Constants.DATEFORMAT_CACHE); //********************************************************************* // Constructor and initialization @@ -183,20 +188,32 @@ private DateFormat createFormatter(Locale loc) throws JspException { DateFormat formatter = null; - if ((type == null) || DATE.equalsIgnoreCase(type)) { - formatter = DateFormat.getDateInstance( - Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"), - loc); - } else if (TIME.equalsIgnoreCase(type)) { - formatter = DateFormat.getTimeInstance( - Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"), - loc); - } 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); - } else { + if ((type == null) || DATE.equalsIgnoreCase(type)) { + 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)) { + 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)) { + 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", type)); @@ -204,4 +221,5 @@ return formatter; } + } Index: src/org/apache/taglibs/standard/util/StandardTaglibCacheFactory.java =================================================================== --- src/org/apache/taglibs/standard/util/StandardTaglibCacheFactory.java (revision 0) +++ src/org/apache/taglibs/standard/util/StandardTaglibCacheFactory.java (revision 0) @@ -0,0 +1,44 @@ +package org.apache.taglibs.standard.util; + +public class StandardTaglibCacheFactory { + + /** + * @throws ClassNotFoundException + * @throws InstantiationException + * @throws IllegalAccessException + */ + public static StandardTaglibCache createCache(String key) { + return createCache(key, null); + } + + /** + * @throws ClassNotFoundException + * @throws InstantiationException + * @throws IllegalAccessException + */ + public static StandardTaglibCache createCache(String key, Class defaultClass) { + + String className = System.getProperty(key); + + try { + if(className == null) { + if(defaultClass == null) { + return null; + } else { + return (StandardTaglibCache) defaultClass.newInstance(); + } + } + + return (StandardTaglibCache) Class.forName(className, true, + Thread.currentThread().getContextClassLoader() + ).newInstance(); + } catch(ClassNotFoundException cnfe) { + throw new RuntimeException("Unable to create cache: " + cnfe); + } catch(IllegalAccessException iae) { + throw new RuntimeException("Unable to create cache: " + iae); + } catch(InstantiationException ie) { + throw new RuntimeException("Unable to create cache: " + ie); + } + } + +} Property changes on: src/org/apache/taglibs/standard/util/StandardTaglibCacheFactory.java ___________________________________________________________________ Name: svn:eol-style + native Index: src/org/apache/taglibs/standard/util/ForeverStandardTaglibCache.java =================================================================== --- src/org/apache/taglibs/standard/util/ForeverStandardTaglibCache.java (revision 0) +++ src/org/apache/taglibs/standard/util/ForeverStandardTaglibCache.java (revision 0) @@ -0,0 +1,22 @@ +package org.apache.taglibs.standard.util; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Objects are cached forever in a Forever cache. + */ +public class ForeverStandardTaglibCache implements StandardTaglibCache { + + private Map map = Collections.synchronizedMap( new HashMap() ); + + public Object get(Object key) { + return map.get(key); + } + + public void put(Object key, Object value) { + map.put(key, value); + } + +} Property changes on: src/org/apache/taglibs/standard/util/ForeverStandardTaglibCache.java ___________________________________________________________________ Name: svn:eol-style + native Index: src/org/apache/taglibs/standard/util/NullStandardTaglibCache.java =================================================================== --- src/org/apache/taglibs/standard/util/NullStandardTaglibCache.java (revision 0) +++ src/org/apache/taglibs/standard/util/NullStandardTaglibCache.java (revision 0) @@ -0,0 +1,15 @@ +package org.apache.taglibs.standard.util; + +/** + * Objects are never cached. + */ +public class NullStandardTaglibCache implements StandardTaglibCache { + + public Object get(Object key) { + return null; + } + + public void put(Object key, Object value) { + } + +} Property changes on: src/org/apache/taglibs/standard/util/NullStandardTaglibCache.java ___________________________________________________________________ Name: svn:eol-style + native Index: src/org/apache/taglibs/standard/util/StandardTaglibCache.java =================================================================== --- src/org/apache/taglibs/standard/util/StandardTaglibCache.java (revision 0) +++ src/org/apache/taglibs/standard/util/StandardTaglibCache.java (revision 0) @@ -0,0 +1,26 @@ +package org.apache.taglibs.standard.util; + +/** + * There are various places in the Standard taglib that + * can really benefit from some caching, however implementing + * a cache with enough options to keep each user happy it + * beyond the scope of the Standard taglib. This interface + * is provided as a plugin point for different cache + * implementations. + */ +public interface StandardTaglibCache { + + /** + * Get an object out of the cache. + * null is returned if there is nothing + * registered under the specified key. + */ + Object get(Object key); + + /** + * Register an object in the cache for a specified key. + * Passing in a value of null unregisters a key. + */ + void put(Object key, Object value); + +} Property changes on: src/org/apache/taglibs/standard/util/StandardTaglibCache.java ___________________________________________________________________ Name: svn:eol-style + native