Author: nbelaevski
Date: 2007-05-01 21:14:48 -0400 (Tue, 01 May 2007)
New Revision: 146
Added:
trunk/framework/src/main/java/org/ajax4jsf/cache/
trunk/framework/src/main/java/org/ajax4jsf/cache/Cache.java
trunk/framework/src/main/java/org/ajax4jsf/cache/CacheEntry.java
trunk/framework/src/main/java/org/ajax4jsf/cache/CacheException.java
trunk/framework/src/main/java/org/ajax4jsf/cache/CacheFactory.java
trunk/framework/src/main/java/org/ajax4jsf/cache/CacheListener.java
trunk/framework/src/main/java/org/ajax4jsf/cache/CacheLoader.java
trunk/framework/src/main/java/org/ajax4jsf/cache/CacheManager.java
trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCache.java
trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java
trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCache.java
trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CacheKey.java
trunk/framework/src/test/java/org/ajax4jsf/cache/
trunk/framework/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
Modified:
trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/CacheContent.java
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CachedResourceContext.java
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/InternetResourceService.java
trunk/test/src/test/java/org/ajax4jsf/framework/resource/InternetResourceServiceTestCase.java
Log:
Switching from OsCache to pluggable caches based on modified JSR-107 API has started
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/Cache.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/Cache.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/Cache.java 2007-05-02 01:14:48 UTC
(rev 146)
@@ -0,0 +1,180 @@
+package org.ajax4jsf.cache;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>
+ * A cache, being a mechanism for efficient temporary storage of objects
+ * for the purpose of improving the overall performance of an application
+ * system, should not be necessary for the application to function correctly,
+ * it only improves the performance.
+ * <p>
+ * A cache could be scoped, for examples to a JVM, all JVMs on a node, all
+ * nodes in a cluster, etc. Operations that are scoped to a cache such as put
+ * or load would affect all JVMs in the cache. So the object loaded in 1 JVM
+ * would be equally available to all other JVMs in the cache.
+ * <p>
+ * Objects are identified in the cache by a key. A key can be any Java
+ * object that implements the equals and hashcode methods. If the object is
+ * to be distributed or persisted (if supported) it must implement
+ * serializable.
+ * <p/>
+ * Each object in the cache will have a <code>CacheEntry<code> object
associated with
+ * it. This object will encapsulate the metadata associated with the cached
+ * object. Mainly it represents the object statistics.
+ * <p/>
+ * "CacheStatistics" represents the read-only statistics of the cache,
+ * while "CacheAttributes" represents the user settable attributes of the
+ * cache.
+ */
+public interface Cache
+{
+ /**
+ * Returns true if the cache contains the specified key. The search is
+ * scoped to the cache. Other caches in the system will not be searched
+ * and a CacheLoader will not be called.
+ * @return true, if the cache contains the specified key.
+ */
+ public boolean containsKey(Object key);
+
+ /**
+ * @return true if the cache contains one or more keys to the specified value.
+ */
+ public boolean containsValue(Object value);
+
+ /**
+ * Returns a set view of the objects currently contained in the cache.
+ * A CacheLoader will not be called. The behavior is unspecified for the
+ * case when an object is remove from the cache while the return set is
+ * being traversed.
+ */
+ public Set entrySet();
+
+ /**
+ * Equality is based on the Set returned by entrySet. Equal will return
+ * true if the two objects are referencing the same object or
+ * entrySet.equals(((Map)o).entrySet()) returns true.
+ */
+ public boolean equals(Object o);
+
+ /**
+ * @param ht a hashtable which holds a pointer pointing to the
+ * declarative cache description.
+ * @throws CacheException if any error occurs.
+ */
+
+ /**
+ * @return the hash code value for this the cache.
+ */
+ public int hashCode();
+
+ /**
+ * @return true if entrySet().isEmpty() returns true.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Returns a set view of the keys currently contained in the cache. A
+ * CacheLoader will not be called. The behavior is unspecified for the
+ * case when an object is remove from the cache while the return set is
+ * being traversed.
+ */
+ public Set keySet();
+
+ /**
+ * Copies all of the mappings from the specified map to the cache. This
+ * would be equivalent to t.entrySet() then iterating through the Set and
+ * calling put with each key value pair.
+ */
+ public void putAll(Map t);
+
+ /**
+ * @return the number of objects in the cache. This should be the same
+ * value as entrySet().size();
+ */
+ public int size();
+
+ /**
+ * @return a collection view of the values contained in the cache.
+ */
+ public Collection values();
+
+ /**
+ * The get method will return, from the cache, the object associated with
+ * the argument "key". If the object is not in the cache, the associated
+ * cache loader will be called. If no loader is associated with the object,
+ * a null is returned. If a problem is encountered during the retrieving
+ * or loading of the object, an exception (to be defined) will be thrown.
+ * If the "arg" argument is set, the arg object will be passed to the
+ * CacheLoader.load method. The cache will not dereference the object.
+ * If no "arg" value is provided a null will be passed to the load method.
+ * The storing of null values in the cache is permitted, however, the get
+ * method will not distinguish returning a null stored in the cache and
+ * not finding the object in the cache. In both cases a null is returned.
+ * @throws CacheException
+ */
+ public Object get(Object key, Object context) throws CacheException;
+
+ /**
+ * The load method provides a means to "pre load" the cache. This method
+ * will, asynchronously, load the specified object into the cache using
+ * the associated cacheloader. If the object already exists in the cache,
+ * no action is taken. If no loader is associated with the object, no object
+ * will be loaded into the cache. If a problem is encountered during the
+ * retrieving or loading of the object, an exception should
+ * be logged.
+ * If the "arg" argument is set, the arg object will be passed to the
+ * CacheLoader.load method. The cache will not dereference the object. If
+ * no "arg" value is provided a null will be passed to the load method.
+ * The storing of null values in the cache is permitted, however, the get
+ * method will not distinguish returning a null stored in the cache and not
+ * finding the object in the cache. In both cases a null is returned.
+ */
+ public void load(Object key, Object context) throws CacheException;
+
+ /**
+ * The peek method will return the object associated with "key" if it
+ * currently exists (and is valid) in the cache. If not, a null is
+ * returned. With "peek" the CacheLoader will not be invoked and other
+ * caches in the system will not be searched.
+ */
+ public Object peek(Object key);
+
+ /**
+ * The put method adds the object "value" to the cache identified by the
+ * object "key".
+ */
+ public Object put(Object key, Object value);
+
+ /**
+ * Returns the CacheEntry object associated with the object identified by
+ * "key". If the object is not in the cache a null is returned.
+ */
+ public CacheEntry getCacheEntry(Object key);
+
+ /**
+ * The remove method will delete the object from the cache including the
+ * key, the associated value and the associated CacheStatistics object.
+ */
+ public Object remove(Object key);
+
+ /**
+ * The clear method will remove all objects from the cache including the
+ * key, the associated value and the associated CacheStatistics object.
+ */
+ public void clear();
+
+ /**
+ * The evict method will remove objects from the cache that are no longer
+ * valid. Objects where the specified expiration time has been reached.
+ */
+ public void evict();
+
+ /** Add a listener to the list of cache listeners */
+ public void addListener(CacheListener listener);
+
+ /** Remove a listener from the list of cache listeners */
+ public void removeListener(CacheListener listener);
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/CacheEntry.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/CacheEntry.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/CacheEntry.java 2007-05-02 01:14:48
UTC (rev 146)
@@ -0,0 +1,29 @@
+package org.ajax4jsf.cache;
+
+import java.util.Map;
+
+/**
+ * CacheEntry
+ *
+ * @author Brian Goetz
+ */
+public interface CacheEntry extends Map.Entry {
+
+ int getHits();
+
+ long getLastAccessTime();
+ long getLastUpdateTime();
+ long getCreationTime();
+ long getExpirationTime();
+
+ /**
+ * Returns a version counter.
+ * An implementation may use timestamps for this or an incrementing
+ * number. Timestamps usually have issues with granularity and are harder
+ * to use across clusteres or threads, so an incrementing counter is often safer.
+ */
+ long getVersion();
+
+ boolean isValid();
+ long getCost();
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/CacheException.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/CacheException.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/CacheException.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -0,0 +1,43 @@
+package org.ajax4jsf.cache;
+
+
+/**
+ * CacheException is a generic exception, which indicates
+ * a cache error has occurred. All the other cache exceptions are the
+ * subclass of this class. All the methods in the cache package only
+ * throw CacheException or the sub class of it.
+ * <P>
+ *
+ */
+public class CacheException extends Exception
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6712594794189413065L;
+
+ /**
+ * Constructs a new CacheException.
+ */
+ public CacheException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new CacheException with a message string.
+ */
+ public CacheException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Constructs a CacheException with a message string, and
+ * a base exception
+ */
+ public CacheException(String s, Throwable ex)
+ {
+ super(s, ex);
+ }
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/CacheFactory.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/CacheFactory.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/CacheFactory.java 2007-05-02 01:14:48
UTC (rev 146)
@@ -0,0 +1,21 @@
+package org.ajax4jsf.cache;
+
+import java.util.Map;
+
+/**
+ * CacheFactory is a service provider specific interface.
+ * Service provider should implement CacheFactory to provide
+ * the functionality to create a new implementation specific Cache object.
+ */
+public interface CacheFactory
+{
+ /**
+ * creates a new implementation specific Cache object using the env parameters.
+ * @param env implementation specific environment parameters passed to the
+ * CacheFactory.
+ * @param cacheLoader implementation of the {@link CacheLoader} to use
+ * @return an implementation specific Cache object.
+ * @throws CacheException if any error occurs.
+ */
+ public Cache createCache(Map env, CacheLoader cacheLoader) throws CacheException;
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/CacheListener.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/CacheListener.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/CacheListener.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -0,0 +1,20 @@
+package org.ajax4jsf.cache;
+
+/** Interface describing various events that can happen as elements are added to
+ * or removed from a cache
+ */
+public interface CacheListener {
+ /** Triggered when a cache mapping is created due to the cache loader being consulted
*/
+ public void onLoad(Object key);
+
+ /** Triggered when a cache mapping is created due to calling Cache.put() */
+ public void onPut(Object key);
+
+ /** Triggered when a cache mapping is removed due to eviction */
+ public void onEvict(Object key);
+
+ /** Triggered when a cache mapping is removed due to calling Cache.remove() */
+ public void onRemove(Object key);
+
+ public void onClear();
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/CacheLoader.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/CacheLoader.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/CacheLoader.java 2007-05-02 01:14:48
UTC (rev 146)
@@ -0,0 +1,24 @@
+package org.ajax4jsf.cache;
+
+
+/**
+ * User should implement this CacheLoader interface to
+ * provide a loader object to load the objects into cache.
+ */
+public interface CacheLoader
+{
+ /**
+ * loads an object. Application writers should implement this
+ * method to customize the loading of cache object. This method is called
+ * by the caching service when the requested object is not in the cache.
+ * <P>
+ *
+ * @param key the key identifying the object being loaded
+ *
+ * @return The object that is to be stored in the cache.
+ * @throws CacheException
+ *
+ */
+ public Object load(Object key, Object context) throws CacheException;
+
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/CacheManager.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/CacheManager.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/CacheManager.java 2007-05-02 01:14:48
UTC (rev 146)
@@ -0,0 +1,113 @@
+package org.ajax4jsf.cache;
+
+import java.io.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * CacheManager is used in J2SE environments for looking up named caches.
+ */
+public class CacheManager {
+
+ private static final String FACTORY_PROPERTY_NAME =
"org.ajax4jsf.cache.CacheFactory";
+ private static final String DEFAULT_FACTORY_NAME =
"org.ajax4jsf.cache.OSCacheCacheFactory";
+
+ protected static CacheManager instance = new CacheManager();
+
+ // REVIEW brian(a)quiotix.com
+ // Should this be a HashMap<String, WeakReference<Cache>>?
+ private final Map caches = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Returns the singleton CacheManager
+ */
+ public static CacheManager getInstance() {
+ return instance;
+ }
+
+ public Cache getCache(String cacheName) {
+ return (Cache) caches.get(cacheName);
+ }
+
+ public void registerCache(String cacheName, Cache cache) {
+ caches.put(cacheName, cache);
+ }
+
+ public CacheFactory getCacheFactory() throws CacheException {
+ String factoryName = findFactory(FACTORY_PROPERTY_NAME);
+
+ try {
+ ClassLoader cl = findClassLoader();
+ Class spiClass = Class.forName(factoryName, true, cl);
+ return (CacheFactory) spiClass.newInstance();
+ } catch (ClassNotFoundException cnfe) {
+ throw new CacheException("Could not find class: '" +
factoryName + "'");
+ } catch (ClassCastException cce) {
+ throw new CacheException("Class: '" + factoryName + "'
does not implement CacheFactory");
+ } catch (InstantiationException ie) {
+ throw new CacheException("Could not instantiate: '" +
factoryName + "'");
+ } catch (IllegalAccessException iae) {
+ throw new CacheException("Could not find public default constructor for:
'" + factoryName + "'");
+ }
+ }
+
+ private ClassLoader findClassLoader() {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ if (cl == null) cl = ClassLoader.getSystemClassLoader();
+ return cl;
+ }
+
+ private boolean isEmptyString(String s) {
+ return s == null || "".equals(s);
+ }
+
+ String findFactory(String factoryId) {
+
+ // Use the system property first
+ try {
+ String factoryClass = System.getProperty(factoryId);
+ if (!isEmptyString(factoryClass)) return factoryClass;
+ } catch (SecurityException ignore) {
+ }
+
+ // try to read from $java.home/lib/jcache.properties
+ try {
+ String configFile = System.getProperty("java.home") +
+ File.separator + "lib" + File.separator +
"jcache.properties";
+ File f = new File(configFile);
+ if (f.exists()) {
+ InputStream in = new FileInputStream(f);
+ try {
+ Properties props = new Properties();
+ props.load(in);
+ String factoryClass = props.getProperty(factoryId);
+ if (!isEmptyString(factoryClass)) return factoryClass;
+ } finally {
+ in.close();
+ }
+ }
+ } catch (SecurityException ignore) {
+ } catch (IOException ignore) {
+ }
+
+ // try to find services in CLASSPATH
+ try {
+ ClassLoader cl = findClassLoader();
+ InputStream is = cl.getResourceAsStream("META-INF/services/" +
factoryId);
+ if (is != null) {
+ BufferedReader r = new BufferedReader(new InputStreamReader(is,
"UTF-8"));
+ try {
+ String factoryName = r.readLine();
+ if (!isEmptyString(factoryName)) return factoryName;
+ } finally {
+ r.close();
+ }
+ }
+ } catch (IOException ignore) {
+ }
+
+ return DEFAULT_FACTORY_NAME;
+ }
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCache.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCache.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCache.java 2007-05-02 01:14:48
UTC (rev 146)
@@ -0,0 +1,120 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.collections.map.LRUMap;
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 01.05.2007
+ *
+ */
+public class LRUMapCache extends LRUMap implements Cache {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3236528957956574490L;
+ private CacheLoader cacheLoader;
+
+ public LRUMapCache(CacheLoader cacheLoader, int initialSize) {
+ super(initialSize);
+ this.cacheLoader = cacheLoader;
+ }
+
+ public LRUMapCache(CacheLoader cacheLoader) {
+ super();
+ this.cacheLoader = cacheLoader;
+ }
+
+ public void addListener(CacheListener listener) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void evict() {
+ // TODO Auto-generated method stub
+
+ }
+
+ private Map futures = new HashMap();
+
+ public Object get(Object key, Object context) throws CacheException {
+
+ try {
+ LRUMapFuture activeFuture = null;
+ LRUMapFuture future = null;
+
+ synchronized (this) {
+ future = (LRUMapFuture) futures.get(key);
+ if (future == null) {
+ activeFuture = new LRUMapFuture();
+ futures.put(key, activeFuture);
+ }
+
+ }
+
+ if (future != null) {
+ synchronized (future) {
+ future.wait();
+ return future.getResult();
+ }
+ } else {
+ synchronized (this) {
+ synchronized (activeFuture) {
+ try {
+ if (!containsKey(key)) {
+ load(key, context);
+ }
+
+ Object result = peek(key);
+ activeFuture.setResult(result);
+
+ return result;
+ } finally {
+ this.futures.remove(key);
+ activeFuture.notifyAll();
+ }
+ }
+ }
+ }
+
+ } catch (InterruptedException e) {
+ throw new CacheException(e.getMessage(), e);
+ }
+ }
+
+ public CacheEntry getCacheEntry(Object key) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public synchronized void load(Object key, Object context) throws CacheException {
+ put(key, cacheLoader.load(key, context));
+ }
+
+ public synchronized Object peek(Object key) {
+ return this.get(key);
+ }
+
+ public void removeListener(CacheListener listener) {
+ // TODO Auto-generated method stub
+
+ }
+}
+
+class LRUMapFuture {
+ private Object result;
+
+ public Object getResult() {
+ return result;
+ }
+
+ public void setResult(Object result) {
+ this.result = result;
+ }
+}
\ No newline at end of file
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -0,0 +1,21 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.Map;
+
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 01.05.2007
+ *
+ */
+public class LRUMapCacheFactory implements CacheFactory {
+
+ public Cache createCache(Map env, CacheLoader cacheLoader)
+ throws CacheException {
+ return new LRUMapCache(cacheLoader);
+ }
+
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCache.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCache.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCache.java 2007-05-02 01:14:48
UTC (rev 146)
@@ -0,0 +1,196 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+
+import com.opensymphony.oscache.base.NeedsRefreshException;
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 01.05.2007
+ *
+ */
+public class OSCacheCache implements Cache {
+
+ private com.opensymphony.oscache.base.Cache cache;
+ private CacheLoader cacheLoader;
+
+ public OSCacheCache(com.opensymphony.oscache.base.Cache cache,
+ CacheLoader cacheLoader) {
+ super();
+ this.cache = cache;
+ this.cacheLoader = cacheLoader;
+ }
+
+ /* (non-Javadoc)
+ * @see
org.ajax4jsf.framework.resource.cache.Cache#addListener(org.ajax4jsf.framework.resource.cache.CacheListener)
+ */
+ public void addListener(CacheListener listener) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#clear()
+ */
+ public void clear() {
+ // TODO Auto-generated method stub
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#containsKey(java.lang.Object)
+ */
+ public boolean containsKey(Object key) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#containsValue(java.lang.Object)
+ */
+ public boolean containsValue(Object value) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#entrySet()
+ */
+ public Set entrySet() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#evict()
+ */
+ public void evict() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#get(java.lang.Object,
java.lang.Object)
+ */
+ public Object get(Object key, Object context) throws CacheException {
+ String keyString = key.toString();
+
+ try {
+ return cache.getFromCache(keyString);
+ } catch (NeedsRefreshException e) {
+ Object object = cacheLoader.load(key, context);
+ try {
+ cache.putInCache(keyString, object);
+ } catch (Exception e1) {
+ cache.cancelUpdate(keyString);
+ throw new CacheException(e1.getMessage(), e1);
+ }
+ return object;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#getCacheEntry(java.lang.Object)
+ */
+ public CacheEntry getCacheEntry(Object key) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#isEmpty()
+ */
+ public boolean isEmpty() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#keySet()
+ */
+ public Set keySet() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#load(java.lang.Object,
java.lang.Object)
+ */
+ public void load(Object key, Object context) throws CacheException {
+ cacheLoader.load(key, context);
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#peek(java.lang.Object)
+ */
+ public Object peek(Object key) {
+ String keyString = key.toString();
+
+ try {
+ return cache.getFromCache(keyString);
+ } catch (NeedsRefreshException e) {
+ cache.cancelUpdate(keyString);
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#put(java.lang.Object,
java.lang.Object)
+ */
+ public Object put(Object key, Object value) {
+ cache.putInCache(key.toString(), value);
+ return value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#putAll(java.util.Map)
+ */
+ public void putAll(Map t) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#remove(java.lang.Object)
+ */
+ public Object remove(Object key) {
+ String keyString = key.toString();
+
+ try {
+ return this.peek(keyString);
+ } finally {
+ cache.removeEntry(keyString);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see
org.ajax4jsf.framework.resource.cache.Cache#removeListener(org.ajax4jsf.framework.resource.cache.CacheListener)
+ */
+ public void removeListener(CacheListener listener) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#size()
+ */
+ public int size() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.Cache#values()
+ */
+ public Collection values() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Added: trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.Map;
+
+
+import com.opensymphony.oscache.general.GeneralCacheAdministrator;
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 01.05.2007
+ *
+ */
+public class OSCacheCacheFactory implements CacheFactory {
+
+ /* (non-Javadoc)
+ * @see org.ajax4jsf.framework.resource.cache.CacheFactory#createCache(java.util.Map,
org.ajax4jsf.framework.resource.cache.CacheLoader)
+ */
+ public Cache createCache(Map env, CacheLoader cacheLoader)
+ throws CacheException {
+ GeneralCacheAdministrator cacheAdministrator = new GeneralCacheAdministrator();
+ return new OSCacheCache(cacheAdministrator.getCache(), cacheLoader);
+ }
+
+}
Modified:
trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/CacheContent.java
===================================================================
---
trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/CacheContent.java 2007-05-01
01:27:27 UTC (rev 145)
+++
trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/CacheContent.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -172,7 +172,7 @@
* @param responseStream
* @return
*/
- public OutputStream getOutputStream(final OutputStream responseStream) {
+ public OutputStream getOutputStream() {
if (null == servletStream) {
outputStream = new FastBufferOutputStream(1024);
servletStream = new ServletOutputStream() {
@@ -185,7 +185,6 @@
public void close() throws IOException {
filledOutputStream = true;
// / content = outputStream.toByteArray();
- responseStream.close();
content = null;
}
@@ -195,7 +194,6 @@
* @see java.io.OutputStream#flush()
*/
public void flush() throws IOException {
- responseStream.flush();
}
/*
@@ -206,7 +204,6 @@
public void write(byte[] b, int off, int len)
throws IOException {
outputStream.write(b, off, len);
- responseStream.write(b, off, len);
}
/*
@@ -216,12 +213,10 @@
*/
public void write(byte[] b) throws IOException {
outputStream.write(b);
- responseStream.write(b);
}
public void write(int b) throws IOException {
outputStream.write(b);
- responseStream.write(b);
}
};
@@ -229,23 +224,20 @@
return servletStream;
}
- public PrintWriter getWriter(final Writer responseWriter) {
+ public PrintWriter getWriter() {
if (null == servletWriter) {
stringOutputWriter = new FastBufferWriter(1024);
Writer out = new Writer() {
public void write(char[] cbuf, int off, int len)
throws IOException {
- responseWriter.write(cbuf, off, len);
stringOutputWriter.write(cbuf, off, len);
}
public void flush() throws IOException {
- responseWriter.flush();
}
public void close() throws IOException {
- responseWriter.close();
// / writerContent = stringOutputWriter.toString();
filledOutputWriter = true;
writerContent = null;
Added: trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CacheKey.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CacheKey.java
(rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CacheKey.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -0,0 +1,41 @@
+/**
+ *
+ */
+package org.ajax4jsf.framework.resource;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 01.05.2007
+ *
+ */
+public class CacheKey {
+ private Object resourceData;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private InternetResource resource;
+ public CacheKey(Object resourceData,
+ HttpServletRequest request, HttpServletResponse response,
+ InternetResource resource) {
+ super();
+ this.resourceData = resourceData;
+ this.request = request;
+ this.response = response;
+ this.resource = resource;
+ }
+ public Object getResourceData() {
+ return resourceData;
+ }
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+ public HttpServletResponse getResponse() {
+ return response;
+ }
+ public InternetResource getResource() {
+ return resource;
+ }
+
+}
Modified:
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CachedResourceContext.java
===================================================================
---
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CachedResourceContext.java 2007-05-01
01:27:27 UTC (rev 145)
+++
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/CachedResourceContext.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -51,7 +51,7 @@
* @see org.ajax4jsf.framework.resource.ResourceContext#getOutputStream()
*/
public OutputStream getOutputStream() throws IOException {
- return content.getOutputStream(this.parent.getOutputStream());
+ return content.getOutputStream();
}
/* (non-Javadoc)
@@ -94,7 +94,6 @@
*/
public void setDateHeader(String name, long value) {
this.content.setDateHeader(name,value);
- this.parent.setDateHeader(name, value);
}
/* (non-Javadoc)
@@ -102,7 +101,6 @@
*/
public void setHeader(String name, String value) {
this.content.setHeader(name,value);
- this.parent.setHeader(name, value);
}
/* (non-Javadoc)
@@ -110,7 +108,6 @@
*/
public void setIntHeader(String name, int value) {
this.content.setIntHeader(name,value);
- this.parent.setIntHeader(name, value);
}
/**
@@ -124,17 +121,14 @@
* @see org.ajax4jsf.framework.resource.ResourceContext#getWriter()
*/
public PrintWriter getWriter() throws IOException {
- // TODO Auto-generated method stub
- return content.getWriter(this.parent.getWriter());
+ return content.getWriter();
}
public void setContentType(String contentType) {
- this.parent.setContentType(contentType);
this.content.setContentType(contentType);
}
public Object getResourceData() {
- // TODO Auto-generated method stub
return parent.getResourceData();
}
@@ -148,13 +142,11 @@
}
public String getServletPath() {
- // TODO Auto-generated method stub
return parent.getServletPath();
}
public void release() {
super.release();
- parent.release();
}
}
Modified:
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/InternetResourceService.java
===================================================================
---
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/InternetResourceService.java 2007-05-01
01:27:27 UTC (rev 145)
+++
trunk/framework/src/main/java/org/ajax4jsf/framework/resource/InternetResourceService.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -23,7 +23,10 @@
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collection;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import javax.faces.FacesException;
@@ -38,6 +41,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.ajax4jsf.cache.Cache;
+import org.ajax4jsf.cache.CacheException;
+import org.ajax4jsf.cache.CacheLoader;
+import org.ajax4jsf.cache.CacheManager;
import org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter;
import org.ajax4jsf.framework.ajax.xmlfilter.CacheContent;
import org.ajax4jsf.framework.util.config.WebXml;
@@ -45,11 +52,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import com.opensymphony.oscache.base.Cache;
-import com.opensymphony.oscache.base.NeedsRefreshException;
-import com.opensymphony.oscache.web.ServletCacheAdministrator;
-public class InternetResourceService {
+public class InternetResourceService implements CacheLoader {
private static final Log log = LogFactory
.getLog(InternetResourceService.class);
@@ -61,7 +65,9 @@
private boolean cacheEnabled = true;
- private ServletCacheAdministrator cacheAdmin;
+ private Cache cache = null;
+
+ //private ServletCacheAdministrator cacheAdmin;
private FacesContextFactory contextFactory;
@@ -88,13 +94,20 @@
.getInitParameter(ENABLE_CACHING_PARAMETER))) {
setCacheEnabled(false);
// this.cacheEnabled = false;
- this.cacheAdmin = null;
+ //this.cacheAdmin = null;
} else {
// Load our implementation properties
Properties cacheProperties = getProperties("oscache.properties");
cacheProperties.putAll(getProperties("/oscache.properties"));
- this.cacheAdmin = ServletCacheAdministrator.getInstance(
- servletContext, cacheProperties);
+ //this.cacheAdmin = ServletCacheAdministrator.getInstance(
+ // servletContext, cacheProperties);
+ Map env = new HashMap();
+ try {
+ this.cache = CacheManager.getInstance().getCacheFactory().createCache(env, this);
+ } catch (CacheException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
// Create Resource-specific Faces Lifecycle instance.
lifecycleClass = servletContext
@@ -169,48 +182,57 @@
String cacheKey = resourceKey;// + "?" +
// request.getQueryString();
// TODO - select session/application scope.
- Cache cache = cacheAdmin.getAppScopeCache(getServletContext());
- try {
+ //Cache cache = cacheAdmin.getAppScopeCache(getServletContext());
+// try {
// TODO - use last modified/expires time
- CacheContent content = (CacheContent) cache
- .getFromCache(cacheKey);
- if (log.isDebugEnabled()) {
- log.debug(Messages.getMessage(
- Messages.GET_CONTENT_FROM_CACHE_INFO, cacheKey));
- }
- content.sendHeaders(response);
- // Correct expires date for resource.
- Date expired = resource.getExpired(null);
- if (expired != null) {
- response.setDateHeader("Expires", expired.getTime());
- } else {
- response.setDateHeader("Expires", System
- .currentTimeMillis()
- + InternetResource.DEFAULT_EXPIRE);
- }
- if (!request.getMethod().equals("HEAD")) {
- content.send(response);
- }
- } catch (NeedsRefreshException e) {
+
+ CacheKey key = new CacheKey(resourceDataForKey, request, response, resource);
+
+ CacheContent content;
try {
- if (log.isDebugEnabled()) {
- log.debug(Messages.getMessage(
- Messages.CONTENT_NOT_FOUND_ERROR, cacheKey));
- }
- CachedResourceContext context = (CachedResourceContext) sendResource(
- resource, request, response, resourceDataForKey);
- // TODO - set refresh interval ?
- cache.putInCache(cacheKey, context.getContent());
- } catch (Exception ex) {
- cache.cancelUpdate(cacheKey);
- log.error(
- Messages.getMessage(Messages.SEND_RESOURCE_ERROR),
- ex);
- throw new ServletException(Messages.getMessage(
- Messages.SEND_RESOURCE_ERROR_2, ex.getMessage()),
- ex);
+ content = (CacheContent) cache
+ .get(cacheKey, key);
+ if (log.isDebugEnabled()) {
+ log.debug(Messages.getMessage(
+ Messages.GET_CONTENT_FROM_CACHE_INFO, cacheKey));
+ }
+ content.sendHeaders(response);
+ // Correct expires date for resource.
+ Date expired = resource.getExpired(null);
+ if (expired != null) {
+ response.setDateHeader("Expires", expired.getTime());
+ } else {
+ response.setDateHeader("Expires", System
+ .currentTimeMillis()
+ + InternetResource.DEFAULT_EXPIRE);
+ }
+ if (!request.getMethod().equals("HEAD")) {
+ content.send(response);
+ }/*
+ } catch (NeedsRefreshException e) {
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug(Messages.getMessage(
+ Messages.CONTENT_NOT_FOUND_ERROR, cacheKey));
+ }
+ CachedResourceContext context = (CachedResourceContext) sendResource(
+ resource, request, response, resourceDataForKey);
+ // TODO - set refresh interval ?
+ cache.put(cacheKey, context.getContent());
+ } catch (Exception ex) {
+ //cache.cancelUpdate(cacheKey);
+ log.error(
+ Messages.getMessage(Messages.SEND_RESOURCE_ERROR),
+ ex);
+ throw new ServletException(Messages.getMessage(
+ Messages.SEND_RESOURCE_ERROR_2, ex.getMessage()),
+ ex);
+ }
+ }*/
+ } catch (CacheException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
- }
} else {
sendResource(resource, request, response, resourceDataForKey);
}
@@ -331,4 +353,31 @@
return resourceBuilder;
}
+ public Object load(Object key, Object context) throws CacheException {
+ CacheKey cacheKey = (CacheKey) context;
+
+ CachedResourceContext resourceContext = (CachedResourceContext)
getResourceContext(cacheKey.getResource(), cacheKey.getRequest(),
+ cacheKey.getResponse());
+ resourceContext.setResourceData(cacheKey.getResourceData());
+ try {
+ getLifecycle().send(resourceContext, cacheKey.getResource());
+ } catch (FacesException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ resourceContext.release();
+
+ // TODO - set refresh interval ?
+ //cache.put(cacheKey, resourceContext.getContent());
+ return resourceContext.getContent();
+ }
+
+ public Map loadAll(Collection keys, Object context) throws CacheException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
Added: trunk/framework/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
===================================================================
--- trunk/framework/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
(rev 0)
+++
trunk/framework/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -0,0 +1,75 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 02.05.2007
+ *
+ */
+public class LRUMapCacheThreadedTest extends TestCase {
+ private CacheLoader cacheLoader = new CacheLoader() {
+
+ public Object load(Object key, Object context) throws CacheException {
+ try {
+ Thread.sleep(new Random().nextInt(100) + 1);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return key;
+ }
+ };
+
+ private static final int COUNT = 2000;
+
+ private final Cache cache = new LRUMapCache(cacheLoader, COUNT);
+
+ public void testCache() throws Exception {
+ Thread[] threads = new Thread[COUNT];
+
+ try {
+ for (int i = 0; i < COUNT; i++) {
+ threads[i] = new TestThread(cache, new Integer(new Random().nextInt(10)));
+ threads[i].start();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ for (int i = 0; i < COUNT; i++) {
+ threads[i].join();
+ }
+ }
+}
+
+class TestThread extends Thread {
+ private Cache cache;
+ private Integer idx;
+
+ public TestThread(Cache cache, Integer idx) {
+ super();
+ this.cache = cache;
+ this.idx = idx;
+ }
+
+ public void run() {
+ super.run();
+
+ try {
+ if (!idx.equals(cache.get(idx, null))) {
+ throw new IllegalStateException();
+ } else {
+ // System.out.println("TestThread.run(): " + idx);
+ }
+ } catch (CacheException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
Modified:
trunk/test/src/test/java/org/ajax4jsf/framework/resource/InternetResourceServiceTestCase.java
===================================================================
---
trunk/test/src/test/java/org/ajax4jsf/framework/resource/InternetResourceServiceTestCase.java 2007-05-01
01:27:27 UTC (rev 145)
+++
trunk/test/src/test/java/org/ajax4jsf/framework/resource/InternetResourceServiceTestCase.java 2007-05-02
01:14:48 UTC (rev 146)
@@ -146,9 +146,6 @@
assertTrue("Resource was generated "+counter+" times", counter<=
10);
}
- /**
- * Test method for {@link
org.ajax4jsf.framework.resource.InternetResourceService#sendResource(org.ajax4jsf.framework.resource.InternetResource,
javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}.
- */
public void testSendResource() {
// fail("Not yet implemented");
}