// // ERXWOResponseCache.java // ERExtensions // // Created by Max Muller on Thu Dec 05 2002. // package er.extensions.appserver; import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.webobjects.appserver.WOApplication; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import er.extensions.foundation.ERXMultiKey; import er.extensions.foundation.ERXProperties; /** * The response cache is a way to cache WOResponse output from a DirectAction * for a given set of cache keys. You can specify the headers, formValues and cookies * to take into account. Your DirectAction class must implement the {@link Cacheable} interface and * should look like this:<pre><code> public class DirectAction extends WODirectAction implements ERXWOResponseCache.Cacheable { static { ERXWOResponseCacheKeyPolicy.sharedInstance().createPolicyEntryForClass(DirectAction.class, new NSArray(new Object[] {"default", "cached"}), NSArray.EmptyArray, NSArray.EmptyArray, NSArray.EmptyArray); } public DirectAction(WORequest aRequest) { super(aRequest); } public WOActionResults notCachedAction() { return pageWithName("NotCached"); } public WOActionResults cachedAction() { return pageWithName("Cached"); } public WOActionResults defaultAction() { return pageWithName("Main"); } } </code></pre> You must also set the default <code>er.extensions.ERXWOResponseCache.Enabled=true</code> for the cache to get used. * * @property er.extensions.ERXWOResponseCache.Enabled */ public class ERXWOResponseCache { /** * Holds a reference to the shared instance */ protected static ERXWOResponseCache sharedInstance; /** * Header key you can set in the response when creating an error page you don't want to get cached. */ public static String NO_CACHE_KEY = "ERXDirectActionRequestHandler.DontCache"; /** * Gets the shared instance * @return the shared instance */ public static ERXWOResponseCache sharedInstance() { if (sharedInstance == null) { sharedInstance = new ERXWOResponseCache(); } return sharedInstance; } public static interface Policy { public boolean actionNameIsCachableForClass(Class actionClass, String actionName); public ERXMultiKey cacheKeyForRequest(Class actionClass, String actionName, WORequest request); public boolean shouldResetCache(); } public static interface Cacheable { } protected Map cache; protected Policy policy; protected Boolean isEnabled; public ERXWOResponseCache() { super(); if (WOApplication.application().isConcurrentRequestHandlingEnabled()) { cache = Collections.synchronizedMap(new HashMap()); } else { cache = new HashMap(); } } public boolean isEnabled() { if (isEnabled == null) { isEnabled = ERXProperties.booleanForKey("er.extensions.ERXWOResponseCache.Enabled") ? Boolean.TRUE : Boolean.FALSE; } return isEnabled.booleanValue(); } public void setIsEnabled(boolean enabled) { isEnabled = (enabled ? Boolean.TRUE : Boolean.FALSE); } public Policy policy() { return policy; } public void setPolicy(Policy policy) { this.policy = policy; } public boolean hasPolicy() { return policy != null; } public boolean actionNameIsCachableForClass(Class actionClass, String actionName) { return hasPolicy() ? policy().actionNameIsCachableForClass(actionClass, actionName) : false; } public void flushCache() { cache.clear(); } public WOResponse cachedResponseForRequest(Class actionClass, String actionName, WORequest request) { if (policy().shouldResetCache()) { flushCache(); } ERXMultiKey cacheKey = policy().cacheKeyForRequest(actionClass, actionName, request); return cacheKey != null ? (WOResponse)cache.get(cacheKey) : null; } public void cacheResponseForRequest(Class actionClass, String actionName, WORequest request, WOResponse response) { if(response.headerForKey(NO_CACHE_KEY) == null) { ERXMultiKey cacheKey = policy().cacheKeyForRequest(actionClass, actionName, request); if (cacheKey != null) { cache.put(cacheKey, response); } } else { response.removeHeadersForKey(NO_CACHE_KEY); } } }