You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wadi-commits@incubator.apache.org by bd...@apache.org on 2005/12/14 23:36:16 UTC

svn commit: r356933 [17/35] - in /incubator/wadi/trunk: ./ etc/ modules/ modules/assembly/ modules/assembly/src/ modules/assembly/src/bin/ modules/assembly/src/conf/ modules/assembly/src/main/ modules/assembly/src/main/assembly/ modules/core/ modules/c...

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/AbstractCacheInnards.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/AbstractCacheInnards.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/AbstractCacheInnards.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/AbstractCacheInnards.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,297 @@
+
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.jcache;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import javax.cache.Cache;
+import javax.cache.CacheEntry;
+import javax.cache.CacheException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.Streamer;
+
+//----------------------------------------
+
+// TODO
+
+// figure out how sessions should be timed out and demoted to next
+// cache (Dummy or e.g. DataBase).
+
+// when cache starts it should loadAll from its dir and from its
+// backing cache (i.e. D.B.)
+
+// sort out touching, versioning and lastModified ttl seems to be on a
+// per-cache basis here, whereas we need it on a per-entry basis.. -
+// extend Cache API ? or just ignore ttl and take via extended Value
+// interface...
+
+// what metadata should live in the CacheEntry and what in the Value ?
+
+// collapse all timing fields together as calculated from each other
+
+//----------------------------------------
+
+public abstract class
+  AbstractCacheInnards
+  implements CacheInnards
+{
+  protected final Log _log=LogFactory.getLog(getClass());
+
+  protected final SerializableContentPool _valuePool;
+  protected final Streamer       _streamingStrategy;
+  protected final Cache                   _cache;
+  protected final EvictionPolicy          _evictionPolicy;
+
+  //----------------------------------------
+
+  public
+    AbstractCacheInnards(SerializableContentPool valuePool, Streamer streamingStrategy, Cache cache, EvictionPolicy evictionPolicy)
+  {
+    assert valuePool!=null;
+    assert streamingStrategy!=null;
+    assert cache!=null;
+    assert evictionPolicy!=null;
+
+    _valuePool         =valuePool;
+    _streamingStrategy =streamingStrategy;
+    _cache             =cache;
+    _evictionPolicy    =evictionPolicy;
+  }
+
+  //----------------------------------------
+  // CacheLoader
+
+  public Object
+    load(Object key)
+    throws CacheException
+  {
+    Object value=loadValue(key);
+
+    if (value==null) {
+        if (_log.isWarnEnabled()) _log.warn("load failed: " + key);
+    } else {
+        if (_log.isInfoEnabled()) _log.info("loaded: " + key + " : " + value);
+    }
+
+    return value;
+  }
+
+  public Map
+    loadAll(Collection keys)
+    throws CacheException
+  {
+    // do we throw an exception if we fail to get one item, or if we
+    // fail to get any ?
+
+    Map map=new HashMap(keys.size());
+    for (Iterator i=keys.iterator(); i.hasNext();)
+    {
+      Object key=i.next();
+      map.put(key, load(key));
+    }
+
+    if (map.size()==0) {
+        if (_log.isWarnEnabled()) _log.warn("loadAll failed: " + keys);
+    } else {
+        if (_log.isInfoEnabled()) _log.info("loadAll: " + map);
+    }
+
+    return map;
+  }
+
+  //----------------------------------------
+  // EvictionPolicy
+
+  public CacheEntry
+    createEntry(Object key, Object value, long ttl)
+  {
+    _log.info("createEntry");
+    return new _CacheEntry(key, value, ttl);	// Pool these ?
+  }
+
+  public void
+    discardEntry(CacheEntry e)
+  {
+      if (_log.isInfoEnabled()) _log.info("discardEntry: " + e);
+    removeValue(e.getKey());
+  }
+
+  public void
+    touchEntry(CacheEntry entry)
+  {
+    _log.info("touchEntry");
+    // update ttl on file ?
+  }
+
+  public void
+    clear()
+  {
+    _log.info("clear");
+    // could remove files one by one - or whole directory ?
+  }
+
+  public Map
+    evict(Cache c)
+  {
+      if (_log.isInfoEnabled()) _log.info("evict: " + c);
+
+    Map evictees=new HashMap();	// TODO - ouch - Maps are expensive - cache ?
+
+    // decide who to evict...
+    for (Iterator i=c.values().iterator(); i.hasNext();)
+    {
+      CacheEntry ce=(CacheEntry)i.next();
+      if (_evictionPolicy.evict(ce))
+	evictees.put(ce.getKey(), ce.getValue()); // TODO - ouch - do we have to load the value ?
+    }
+
+    return evictees;
+  }
+
+  //----------------------------------------
+  // CacheEntry - a File on local disc
+
+  class
+    _CacheEntry
+    implements CacheEntry
+  {
+    protected long    _cost;
+    protected long    _creationTime;
+    protected long    _expirationTime;
+    protected int     _hits;
+    protected long    _lastAccessedTime;
+    protected long    _lastUpdateTime;
+    protected long    _version;
+    protected boolean _valid=true;
+    protected Object  _key;
+    protected long    _ttl;
+
+    _CacheEntry(Object key, Object value, long ttl)
+    {
+      addValue(_key=key, value);
+      _ttl=ttl;
+    }
+
+    // CacheEntry
+
+    public long
+      getCost()
+    {
+      _log.info("getCost");
+      return _cost;
+    }
+
+    public long
+      getCreationTime()
+    {
+      _log.info("getCreationTime");
+      return _creationTime;
+    }
+
+    public long
+      getExpirationTime()
+    {
+      _log.info("getExpirationTime");
+      return _expirationTime;
+    }
+
+    public int
+      getHits()
+    {
+      _log.info("getHits");
+      return _hits;
+    }
+
+    public long
+      getLastAccessTime()
+    {
+      _log.info("getLastAccessTime");
+      return _lastAccessedTime;
+    }
+
+    public long
+      getLastUpdateTime()
+    {
+      _log.info("getLastUpdateTime");
+      return _lastUpdateTime;
+    }
+
+    public long
+      getVersion()
+    {
+      _log.info("getVersion");
+      return _version;
+    }
+
+    public boolean
+      isValid()
+    {
+      _log.info("isValid");
+      return _valid;
+    }
+
+    public Object getKey(){return _key;}
+
+    public Object
+      getValue()
+    {
+      return loadValue(_key);
+    }
+
+    public Object
+      setValue(Object value)
+    {
+      Object oldValue=loadValue(_key); // TODO - optimisation - will this ever be used ?
+      storeValue(_key, value);
+      return oldValue;
+    }
+
+    public String
+      toString()
+    {
+      return "<"+getClass().getName()+": "+_key+">";
+    }
+
+    public int
+      hashCode()
+    {
+      _log.info("hashCode");
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean
+      equals()
+    {
+      _log.info("equals");
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  //----------------------------------------
+  // internals
+
+  public abstract String toString();
+  protected abstract Object loadValue(Object key);
+  protected abstract boolean storeValue(Object key, Object value);
+  protected abstract boolean addValue(Object key, Object value);
+  protected abstract boolean removeValue(Object key);
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/CacheInnards.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/CacheInnards.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/CacheInnards.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/CacheInnards.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,29 @@
+
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.jcache;
+
+import javax.cache.CacheLoader;
+import javax.cache.EvictionStrategy;
+
+public interface
+  CacheInnards
+  extends CacheLoader, EvictionStrategy
+{
+}
+

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/EvictionPolicy.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/EvictionPolicy.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/EvictionPolicy.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/EvictionPolicy.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,37 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 15, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.jcache;
+
+import javax.cache.CacheEntry;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface EvictionPolicy {
+
+	boolean evict(CacheEntry e);
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/LocalDiscCacheInnards.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/LocalDiscCacheInnards.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/LocalDiscCacheInnards.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/LocalDiscCacheInnards.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,154 @@
+
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.jcache;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import javax.cache.Cache;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.SerializableContent;
+import org.codehaus.wadi.Streamer;
+
+//----------------------------------------
+
+// assumption - we are the only people reading and writing to this
+// directory... - should be dynamically created to ensure this...
+
+// if we know the cache is homogeneous (only stores one type), we do
+// not need to write type information into every evicted file... -
+// hence SerializableContent...
+
+//----------------------------------------
+
+public class
+  LocalDiscCacheInnards
+  extends AbstractCacheInnards
+{
+  protected final Log _log=LogFactory.getLog(getClass());
+
+  protected final File                    _dir;
+
+  //----------------------------------------
+
+  public
+    LocalDiscCacheInnards(File dir, SerializableContentPool valuePool, Streamer streamingStrategy, Cache cache, EvictionPolicy evictionPolicy)
+  {
+    super(valuePool, streamingStrategy, cache, evictionPolicy);
+    assert dir.exists();
+    assert dir.isDirectory();
+    assert dir.canRead();
+    assert dir.canWrite();
+
+    _dir               =dir;
+      if (_log.isInfoEnabled()) _log.info("created: " + this);
+  }
+
+  public String
+    toString()
+  {
+    return "<"+getClass().getName()+":"+_dir+", "+_valuePool+", "+_cache+">";
+  }
+
+  // need to think about whether to catch exception here or in code above...
+  protected Object
+    loadValue(Object key)
+  {
+    Object value=null;
+
+    File file=new File(_dir, key.toString()+"."+_streamingStrategy.getSuffix());
+    if (file.exists())
+    {
+      try
+      {
+	SerializableContent sc=_valuePool.take();
+	ObjectInput oi=_streamingStrategy.getInputStream(new FileInputStream(file));
+	sc.readContent(oi);
+	oi.close();
+
+	value=sc;
+          if (_log.isInfoEnabled()) _log.info("loaded (local disc): " + key + " : " + value);
+      }
+      catch (Exception e)
+      {
+          if (_log.isErrorEnabled()) _log.error("load (local disc) failed: " + key, e);
+      }
+    }
+
+    return value;
+  }
+
+  protected boolean
+    storeValue(Object key, Object value)
+  {
+    boolean success=false;
+
+    try
+    {
+      SerializableContent sc=(SerializableContent)value;
+      File file=new File(_dir, key.toString()+"."+_streamingStrategy.getSuffix());
+      ObjectOutput oos=_streamingStrategy.getOutputStream(new FileOutputStream(file));
+      sc.writeContent(oos);
+      oos.flush();
+      oos.close();
+
+      // do we need to worry about ttl ?
+      //	long willTimeOutAt=impl.getLastAccessedTime()+(impl.getMaxInactiveInterval()*1000);
+      //	file.setLastModified(willTimeOutAt);
+
+        if (_log.isInfoEnabled()) _log.info("stored (local disc): " + key + " : " + value);
+      success=true;
+    }
+    catch (Exception e)
+    {
+        if (_log.isErrorEnabled()) _log.error("store (local disc) failed: " + key, e);
+    }
+
+    return success;
+  }
+
+  protected boolean
+  	addValue(Object key, Object value)
+  {
+  	return storeValue(key, value);
+  }
+
+  protected boolean
+    removeValue(Object key)
+  {
+    boolean success=false;
+
+    try
+    {
+      File file=new File(_dir, key.toString()+"."+_streamingStrategy.getSuffix());
+      file.delete();
+        if (_log.isInfoEnabled()) _log.info("removed (local disc): " + key);
+      success=true;
+    }
+    catch (Exception e)
+    {
+        if (_log.isErrorEnabled()) _log.error("removal (local disc) failed: " + key, e);
+    }
+
+    return success;
+  }
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SerializableContentPool.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SerializableContentPool.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SerializableContentPool.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SerializableContentPool.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,39 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 15, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.jcache;
+
+import org.codehaus.wadi.SerializableContent;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface SerializableContentPool {
+
+	SerializableContent take();
+
+	SerializableContent poll(long msecs);
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SharedDBCacheInnards.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SharedDBCacheInnards.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SharedDBCacheInnards.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/SharedDBCacheInnards.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,196 @@
+
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.jcache;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import javax.cache.Cache;
+import javax.sql.DataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.SerializableContent;
+import org.codehaus.wadi.Streamer;
+
+//----------------------------------------
+
+// first, and very rudimentary, shot at a DB-backed JCache - lots of
+// work to do here...
+
+// shouldn't be caching keys...
+
+// refactor and merge as much as possible with LocalDiscCacheInnards
+//----------------------------------------
+
+class
+  SharedDBCacheInnards
+  extends AbstractCacheInnards
+{
+  protected final Log _log=LogFactory.getLog(getClass());
+
+  protected final DataSource              _ds;
+  protected final String                  _table;
+
+  //----------------------------------------
+
+  public
+    SharedDBCacheInnards(DataSource ds, String table, SerializableContentPool valuePool, Streamer streamingStrategy, Cache cache, EvictionPolicy evictionPolicy)
+  {
+    super(valuePool, streamingStrategy, cache, evictionPolicy);
+    assert ds!=null;
+    assert table!=null;
+
+    _ds                =ds;
+    _table             =table;
+      if (_log.isInfoEnabled()) _log.info("created: " + this);
+  }
+
+  public String
+    toString()
+  {
+    return "<"+getClass().getName()+":"+_ds+", "+_table+", "+_valuePool+", "+_cache+">";
+  }
+
+  // need to think about whether to catch exception here or in code above...
+  protected Object
+    loadValue(Object key)
+  {
+    Object value=null;
+    try
+    {
+      Connection c=_ds.getConnection();
+      Statement s=c.createStatement();
+      ResultSet rs=s.executeQuery("SELECT MyValue FROM "+_table+" WHERE MyKey='"+key+"'");
+      if (rs.next())
+      {
+    	SerializableContent sc=_valuePool.take();
+    	ObjectInput oi=_streamingStrategy.getInputStream(new ByteArrayInputStream((byte[])rs.getObject(1)));
+    	sc.readContent(oi);
+    	oi.close();
+
+    	value=sc;
+          if (_log.isInfoEnabled()) _log.info("loaded (database): " + key + " : " + value);
+      }
+
+      s.close();
+      c.close();
+    }
+    catch (Exception e)
+    {
+        if (_log.isErrorEnabled()) _log.error("loading (database) failed: " + key, e);
+    }
+
+    return value;
+  }
+
+  protected boolean
+    storeValue(Object key, Object value)
+  {
+    boolean success=false;
+
+    try
+    {
+ //     SerializableContent sc=(SerializableContent)value;
+
+      Connection c=_ds.getConnection();
+      PreparedStatement ps=c.prepareStatement("UPDATE "+_table+" SET MyValue=? WHERE MyKey='"+key.toString()+"'");
+      ps.setObject(1, value);
+      ps.executeUpdate();
+      ps.close();
+      c.close();
+
+      // do we need to worry about ttl ?
+      //	long willTimeOutAt=impl.getLastAccessedTime()+(impl.getMaxInactiveInterval()*1000);
+      //	file.setLastModified(willTimeOutAt);
+
+        if (_log.isInfoEnabled()) _log.info("stored (database): " + key + " : " + value);
+      success=true;
+    }
+    catch (Exception e)
+    {
+        if (_log.isErrorEnabled()) _log.error("eviction (database) failed: " + key, e);
+    }
+
+    return success;
+  }
+
+  protected boolean
+  	addValue(Object key, Object value)
+  {
+    boolean success=false;
+
+    try
+    {
+      SerializableContent sc=(SerializableContent)value;
+
+      Connection c=_ds.getConnection();
+      PreparedStatement ps=c.prepareStatement("INSERT INTO "+_table+" (MyKey, MyValue) VALUES ('"+key.toString()+"', ?)");
+      ByteArrayOutputStream baos=new ByteArrayOutputStream();
+      ObjectOutput oos=_streamingStrategy.getOutputStream(baos);
+      sc.writeContent(oos);
+      oos.flush();
+      oos.close();
+      ps.setObject(1, baos.toByteArray());
+      ps.executeUpdate();
+      ps.close();
+      c.close();
+
+      // do we need to worry about ttl ?
+      //	long willTimeOutAt=impl.getLastAccessedTime()+(impl.getMaxInactiveInterval()*1000);
+      //	file.setLastModified(willTimeOutAt);
+
+        if (_log.isInfoEnabled()) _log.info("stored (database): " + key + " : " + value);
+      success=true;
+    }
+    catch (Exception e)
+    {
+        if (_log.isErrorEnabled()) _log.error("eviction (database) failed: " + key, e);
+    }
+
+    return success;
+  }
+  protected boolean
+    removeValue(Object key)
+  {
+    boolean success=false;
+
+    try
+    {
+      Connection c=_ds.getConnection();
+      Statement s=c.createStatement();
+      s.executeUpdate("DELETE FROM "+_table+" WHERE MyKey='"+key+"'");
+      s.close();
+      c.close();
+
+        if (_log.isInfoEnabled()) _log.info("removed (database): " + key);
+      success=true;
+    }
+    catch (Exception e)
+    {
+        if (_log.isErrorEnabled()) _log.error("removal (database) failed: " + key, e);
+    }
+
+    return success;
+  }
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/TestJCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/TestJCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/TestJCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/jcache/TestJCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,319 @@
+
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.jcache;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.sql.Connection;
+import java.sql.Statement;
+import javax.cache.Cache;
+import javax.cache.CacheEntry;
+import javax.sql.DataSource;
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.axiondb.jdbc.AxionDataSource;
+import org.codehaus.wadi.SerializableContent;
+import org.codehaus.wadi.impl.SimpleStreamer;
+
+import ri.cache.BasicCache;
+
+// WADI should use a JSR107 compatible API for its session Map
+
+// InVM Cache - in memory map of session-id:session
+// LocalStore Cache - evicted sessions move to an EvictionStore (e.g. spooled to Disc)
+// SharedStore Cache - When there are less than the required number of copies i.e. DataBase...
+// Distributed Tier - a Session may be 'owned' by another node - ownership may be changed by 'migration'
+// Replicated Tier -A Session may be replicated to allow redundant copies to be held off-node
+
+// is it local ?
+// has it been evicted ?
+// can it be migrated ?
+// can it be restored from a replicated copy ?
+
+// N.B.
+
+// If the node (n1) owning 'xyz' fails and a request for 'xyz' falls
+// on another node (n2) what happens ?
+
+// notification of n1's death may not have reached everybody, so no-one
+// will have had time to adopt n's orphans.
+
+// n2 must local n1's buddies. everyone must agree that n1 has
+// died. n2 may then adopt ownership of 'xyz'.
+
+// what happens to remaining orphanned sessions ?
+
+// they must be immediately adopted (i.e. pushed up into higher tiers
+// of cache) since this will improve cluster performance and they are
+// at risk if only held by (n-1) buddies where n is the lowest safe
+// number of copies specified by the admin.
+
+// so n2 may adopt a slice of n1's sessions and other nodes may adopt
+// the rest...
+
+// if n1 was buddying for anyone, that node will be responsible for
+// recruiting a new buddy and synching them with the partition's
+// state.
+
+// This all needs to be backed by a LARGE, SHARED store. When no node
+// in the cluster is running, sessions should be persisted to this
+// store...
+
+// last-one-out-turns-out-the-lights might be good enough, provided
+// that the first/last node does not crash... (crashing is a
+// kill-9-level concern, so replication should protect against this -
+// how?).
+
+// first node up (n1) should promote a COPY of shared store to its own
+// local store.
+
+// n2 should join n1's buddy group and replicate its VM and Local tiers...
+
+// etc... until n is reached, when SharedTier may be emptied.
+
+// if all nodes die before n is reached, new n1 will reread from
+// SharedTier...
+
+// as node numbers fall below n - what happens ? does everyone evict
+// and replicate direct to shared store ?
+
+// perhaps the sharedStore tier could maintain a ref-count on each
+// item, so it knows when it is safe and can be promoted/removed ?
+// more thought needed...
+
+// shared vs. remote - how far down stack should we search for state...
+
+// use serialisation adaptor rather than insisting state implements
+// e.g. SerializableContent...
+
+//----------------------------------------
+
+public class
+  TestJCache
+  extends TestCase
+{
+  protected Log _log=LogFactory.getLog(TestJCache.class);
+
+  public TestJCache(String name) {super(name);}
+
+  protected void
+    setUp()
+    throws Exception
+    {
+      _log.info("starting test");
+    }
+
+  protected void
+    tearDown()
+    throws InterruptedException
+    {
+      _log.info("stopping test");
+    }
+
+  class
+    Value
+    implements SerializableContent
+  {
+    protected String _value;
+
+    Value(){}
+
+    Value(String value)
+    {
+      _value=value;
+    }
+
+    public String
+      getValue()
+    {
+      return _value;
+    }
+
+    public String
+      toString()
+    {
+      return "<"+getClass().getName()+":"+_value+">";
+    }
+
+    public void
+      readContent(ObjectInput is)
+      throws IOException, ClassNotFoundException
+    {
+      _value=(String)(is.readObject());
+    }
+
+    public void
+      writeContent(ObjectOutput os)
+      throws IOException
+    {
+      os.writeObject(_value);
+    }
+
+    public boolean
+      equals(Object o)
+    {
+      if (o==this)
+	return true;
+
+      if (o==null || !(o instanceof Value))
+	return false;
+
+      Value that=(Value)o;
+
+      return this._value.equals(that._value);
+    }
+  }
+
+  // modelled on Doug Lea's Takable/Channel
+  class
+    Pool
+    implements SerializableContentPool
+  {
+    public SerializableContent poll(long msecs){return new Value();}
+    public SerializableContent take(){return new Value();}
+  }
+
+  class
+    NoEvictionPolicy
+    implements EvictionPolicy
+  {
+    public boolean evict(CacheEntry ce){return false;}
+  }
+
+  protected void
+    testJCache(Cache c, boolean byRef)
+  {
+    boolean success=false;
+
+    try
+    {
+      String key="key-1";
+      Value val=new Value("value-1");
+
+      c.put(key, val);
+
+      Value first=(Value)c.get(key);
+      assertTrue(val.equals(first));
+      Value second=(Value)c.get(key);
+      assertTrue(val.equals(second));
+      assertTrue(byRef?(first==second):(first.equals(second)));
+
+      c.containsKey(key);
+      c.containsKey(key);
+      c.containsKey(key);
+      c.containsKey(key);
+      c.containsKey(key);
+      c.containsKey(key);
+
+//       c.remove(key);
+//       assertTrue(c.get(key)==null);
+
+//       c.evict();
+//       c.get("key-2");
+
+      success=true;
+    }
+    catch (Exception e)
+    {
+      _log.error("test failed", e);
+    }
+
+    assertTrue(success);
+  }
+
+  public void
+    testRI()
+  {
+    Cache cache=new BasicCache();
+
+    testJCache(cache, true);
+  }
+
+  public void
+    testDisc()
+    throws Exception
+  {
+    // ugly - is there a better way - createTempDir ?
+    File tmp=File.createTempFile("TestJCache-", "", new File("/tmp"));
+    String name=tmp.toString();
+    tmp.delete();
+    File dir=new File(name);
+      if (_log.isInfoEnabled()) _log.info("dir=" + dir);
+    assertTrue(dir.mkdirs());
+
+    Cache backing=new BasicCache();
+    CacheInnards ci=new LocalDiscCacheInnards(dir, new Pool(), new SimpleStreamer(), backing, new NoEvictionPolicy());
+    Cache cache=new BasicCache(ci, ci);
+
+    testJCache(cache, false);
+
+    dir.delete();
+  }
+
+  // once we have a working DB-based cache we can back the file-based
+  // on onto it, so expiring sessions are demoted to persistant
+  // storage...
+  public void
+    testDB()
+    throws Exception
+  {
+    boolean success=false;
+
+    try
+    {
+      DataSource ds=new AxionDataSource("jdbc:axiondb:testdb");	// db springs into existance in-vm beneath us
+      String table="MyTable";
+
+      {
+	Connection c=ds.getConnection();
+	Statement s=c.createStatement();
+	// TODO - should parameterise the column names when code stabilises...
+	s.execute("create table "+table+"(MyKey varchar, MyValue java_object)");
+	s.close();
+	c.close();
+      }
+
+      Cache backing=new BasicCache();
+      CacheInnards ci=new SharedDBCacheInnards(ds, table, new Pool(), new SimpleStreamer(), backing, new NoEvictionPolicy());
+      Cache cache=new BasicCache(ci, ci);
+
+      testJCache(cache, false);
+
+      {
+	Connection c=ds.getConnection();
+	Statement s=c.createStatement();
+	s.execute("drop table "+table);
+	s.execute("SHUTDOWN");
+	s.close();
+	c.close();
+      }
+
+      success=true;
+    }
+    catch (Exception e)
+    {
+      _log.error("test failed", e);
+    }
+
+    assertTrue(success);
+  }
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/Cluster.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/Cluster.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/Cluster.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/Cluster.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,26 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.partition;
+
+public interface Cluster {
+
+	void start() throws Exception;
+	void stop() throws Exception;
+
+	String getNodeName(Object node);
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/ACCluster.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/ACCluster.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/ACCluster.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/ACCluster.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,97 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.partition.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.JMSException;
+
+import org.activecluster.ClusterEvent;
+import org.activecluster.ClusterFactory;
+import org.activecluster.ClusterListener;
+import org.activecluster.Node;
+import org.activecluster.impl.DefaultClusterFactory;
+import org.activemq.ActiveMQConnectionFactory;
+//import org.activemq.store.vm.VMPersistenceAdapterFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.sandbox.partition.Cluster;
+
+public class ACCluster implements Cluster {
+
+	protected final Log _log = LogFactory.getLog(getClass());
+
+	//protected final String _clusterUri="tcp://smilodon:61616";
+	protected final String _clusterUri="peer://org.codehaus.wadi?persistent=false";
+    protected final String _clusterName="ORG.CODEHAUS.WADI.TEST";
+    protected final ActiveMQConnectionFactory _connectionFactory=new ActiveMQConnectionFactory(_clusterUri);
+    protected final ClusterFactory _clusterFactory=new DefaultClusterFactory(_connectionFactory);
+	protected final org.activecluster.Cluster _cluster;
+	protected final long _timeout=30*1000L;
+
+	public ACCluster(String nodeName) throws Exception {
+		//System.setProperty("activemq.persistenceAdapterFactory", VMPersistenceAdapterFactory.class.getName());
+		_cluster=_clusterFactory.createCluster(_clusterName);
+		Map state=new HashMap();
+		state.put("nodeName", nodeName);
+		_cluster.getLocalNode().setState(state);
+		_cluster.addClusterListener(new ClusterListener() {
+
+			public void onNodeAdd(ClusterEvent arg0) {
+                if (_log.isInfoEnabled()) _log.info("onNodeAdd: " + getNodeName(arg0.getNode()));
+			}
+
+			public void onNodeUpdate(ClusterEvent arg0) {
+                if (_log.isInfoEnabled()) _log.info("onNodeUpdate: " + getNodeName(arg0.getNode()));
+			}
+
+			public void onNodeRemoved(ClusterEvent arg0) {
+                if (_log.isInfoEnabled()) _log.info("onNodeRemoved: " + getNodeName(arg0.getNode()));
+			}
+
+			public void onNodeFailed(ClusterEvent arg0) {
+                if (_log.isInfoEnabled()) _log.info("onNodeFailed: " + getNodeName(arg0.getNode()));
+			}
+
+			public void onCoordinatorChanged(ClusterEvent arg0) {
+                if (_log.isInfoEnabled()) _log.info("onCoordinatorChanged: " + getNodeName(arg0.getNode()));
+			}
+		});
+	}
+
+	public String getNodeName(Object node) {
+		return (String)((Node)node).getState().get("nodeName");
+	}
+
+	public void start() throws JMSException {
+	  _log.info("starting...");
+		_cluster.start();
+		_log.info("...started");
+	}
+
+	public void stop() {
+
+	}
+
+	public static void main(String[] args) throws Exception {
+		Cluster cluster=new ACCluster(args[0]);
+		cluster.start();
+		Thread.sleep(100*1000);
+		cluster.stop();
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/TestExchange.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/TestExchange.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/TestExchange.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/partition/impl/TestExchange.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,115 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.sandbox.partition.impl;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import junit.framework.TestCase;
+
+public class TestExchange extends TestCase {
+
+	protected final Log _log = LogFactory.getLog(getClass());
+
+	public static void main(String[] args) {
+	}
+
+	public TestExchange(String arg0) {
+		super(arg0);
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+	}
+
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+
+	static class Node {
+
+		public Node(int numPartitionsInCluster) {
+			_numPartitionsInCluster=numPartitionsInCluster;
+			_numPartitionsOwned=numPartitionsInCluster;
+			_numNodesInCluster=1;
+		}
+
+		public Node() {
+		}
+
+		int _numPartitionsInCluster;
+		int _numPartitionsOwned;
+		int _numNodesInCluster;
+
+		public String toString() {
+			return (""+_numPartitionsOwned+"/"+_numPartitionsInCluster+"/"+_numNodesInCluster);
+		}
+	}
+
+	public void join(List cluster, Node node) {
+		for (Iterator i=cluster.iterator(); i.hasNext();) {
+			Node n=(Node)i.next();
+			node._numPartitionsInCluster=n._numPartitionsInCluster;
+			node._numNodesInCluster= ++n._numNodesInCluster;
+
+			int src=n._numPartitionsOwned;
+			int tgt=node._numPartitionsOwned;
+
+			while (tgt<numPartitionsPerNode && src>numPartitionsPerNode) {
+				tgt++;
+				src--;
+			}
+
+			n._numPartitionsOwned=src;
+			node._numPartitionsOwned=tgt;
+		}
+
+		cluster.add(node);
+	}
+
+	protected int numPartitions=1024;
+	protected int numNodes=100;
+	protected int numPartitionsPerNode=numPartitions/numNodes;
+
+	public void testExchange() throws Exception {
+
+
+		List cluster=new ArrayList();
+
+		cluster.add(new Node(numPartitions));
+
+		for (int i=1; i<numNodes; i++) {
+			join(cluster, new Node());
+		}
+
+		int numPartitionsInCluster=0;
+		for (Iterator i=cluster.iterator(); i.hasNext(); ) {
+			Node node=(Node)i.next();
+			assertTrue(node._numPartitionsInCluster==numPartitions);
+			assertTrue(node._numPartitionsOwned==numPartitionsPerNode || node._numPartitionsOwned==(numPartitionsPerNode+1));
+			numPartitionsInCluster+=node._numPartitionsOwned;
+            if (_log.isInfoEnabled()) _log.info("node[" + i + "]: " + node);
+		}
+		assertTrue(numPartitionsInCluster==numPartitions);
+
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/Cache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/Cache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/Cache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/Cache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,43 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache;
+
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface Cache {
+	public RequestProcessor put(String key, RequestProcessor rp);
+	public RequestProcessor get(String id);
+	public RequestProcessor peek(String id);
+	public RequestProcessor remove(String id);
+	public void evict();
+	public boolean isOffNode();
+
+	interface Evicter {
+		boolean evict(String key, RequestProcessor val);
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/RequestProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/RequestProcessor.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/RequestProcessor.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/RequestProcessor.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,46 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.codehaus.wadi.SerializableContent;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface RequestProcessor extends SerializableContent {
+	void process(ServletRequest req, ServletResponse res, FilterChain chain);
+
+	// temporary
+	public long getTimeToLive();
+	public void setTimeToLive(long ttl);
+
+	public int getMaxInactiveInterval();
+	public void setMaxInactiveInterval(int mii);
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/TestCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/TestCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/TestCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/TestCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,156 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.impl.SimpleStreamer;
+import org.codehaus.wadi.sandbox.wcache.impl.ClusterCache;
+import org.codehaus.wadi.sandbox.wcache.impl.InactiveEvicter;
+import org.codehaus.wadi.sandbox.wcache.impl.InvalidEvicter;
+import org.codehaus.wadi.sandbox.wcache.impl.JDBCCache;
+import org.codehaus.wadi.sandbox.wcache.impl.LocalDiscCache;
+import org.codehaus.wadi.sandbox.wcache.impl.MaxInactiveIntervalEvicter;
+import org.codehaus.wadi.sandbox.wcache.impl.MemoryCache;
+import org.codehaus.wadi.sandbox.wcache.impl.NeverEvicter;
+
+import junit.framework.TestCase;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class TestCache extends TestCase {
+	protected static Log _log = LogFactory.getLog(TestCache.class);
+
+	/*
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+	}
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	/**
+	 * Constructor for TestCache.
+	 * @param arg0
+	 */
+	public TestCache(String arg0) {
+		super(arg0);
+	}
+
+	class MyRequestProcessor implements RequestProcessor {
+		String _content;
+
+		public MyRequestProcessor(String content) {
+			_content=content;
+		}
+
+		public boolean equals(Object o) {
+			if (o instanceof MyRequestProcessor) {
+				MyRequestProcessor that=(MyRequestProcessor)o;
+				return this._content.equals(that._content);
+			}
+			else
+				return false;
+		}
+
+		public void process(ServletRequest req, ServletResponse res, FilterChain chain) {
+            if (_log.isInfoEnabled()) _log.info("processing MyRequest: " + _content);
+		}
+
+		protected long _ttl;
+		public long getTimeToLive() {return _ttl;}
+		public void setTimeToLive(long ttl) {_ttl=ttl;}
+
+		protected int _mii;
+		public int getMaxInactiveInterval() {return _mii;}
+		public void setMaxInactiveInterval(int mii) {_mii=mii;}
+
+
+		public void readContent(ObjectInput is)
+		    throws IOException, ClassNotFoundException {
+			_content=(String)is.readObject();
+		  }
+
+		public void writeContent(ObjectOutput os)
+		    throws IOException {
+			os.writeObject(_content);
+		  }
+		}
+
+
+	public void testCacheStack()
+	throws Exception
+	{
+	    // ugly - is there a better way - createTempDir ?
+	    File f=File.createTempFile("TestJCache-", "", new File("/tmp"));
+	    String name=f.toString();
+	    f.delete();
+	    File dir=new File(name);
+        if (_log.isInfoEnabled()) _log.info("dir=" + dir);
+	    assertTrue(dir.mkdirs());
+
+	    // TODO - insert Replicated and DB cache tiers here...
+		Cache database=new JDBCCache(new NeverEvicter(), null);
+		Cache cluster=new ClusterCache(new InvalidEvicter(), database);
+		Cache disc=new LocalDiscCache(dir, new SimpleStreamer(), new MaxInactiveIntervalEvicter(), cluster);
+		Cache cache=new MemoryCache(new InactiveEvicter(), disc);
+
+		String key="xxx";
+		RequestProcessor val=new MyRequestProcessor("test");
+		val.setTimeToLive(0);
+		cache.put(key, val);
+		cache.evict();
+		disc.evict();
+
+//		RequestProcessor tmp=cache.get(key);
+//
+//		assertTrue(val.equals(tmp));
+//
+//		tmp.process(null, null, null);
+//
+//		String k="foo";
+//		RequestProcessor foo=new MyRequestProcessor(k);
+//		cluster.put(k, foo);
+//
+//		cache.get(k).process(null, null, null);
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,106 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.sandbox.wcache.Cache;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public abstract class AbstractCache implements Cache {
+	protected Log _log = LogFactory.getLog(getClass());
+
+	protected Evicter _evicter;
+	protected Cache _subcache;
+
+	public AbstractCache(Evicter evicter, Cache subcache) {
+		_evicter=evicter;
+		_subcache=subcache;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#put(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public abstract RequestProcessor put(String key, RequestProcessor val);
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#get(java.lang.String)
+	 */
+	public RequestProcessor get(String key) {
+		RequestProcessor val=peek(key);
+		if (val==null)
+			val=promote(key, _subcache);
+		return val;
+	}
+
+	// TODO - optimise and further abstract so transactional caches can do their things etc..
+	protected RequestProcessor promote(String key, Cache subcache) {
+		RequestProcessor val=null;
+		key=key.intern(); // all threads will now have same ref for key
+		synchronized (key) {
+			// we may have been waiting a while - check load() has not already occurred..
+			if ((val=peek(key))==null)
+			{
+				// if val is not bound no load() has occurred - since an unsuccessful load
+				// will return some form of RP for a dead session...
+				val=subcache.get(key);
+				put(key, val);
+				_subcache.remove(key);
+                if (_log.isInfoEnabled()) _log.info("promoted: " + key + " from " + subcache);
+			}
+		}
+		return val;
+	}
+
+//	protected RequestProcessor demote(String key, RequestProcessor val, Cache subcache) {
+//		remove(key);
+//		subcache.put(key, val);
+//		return val;
+//	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#peek(java.lang.String)
+	 */
+	public abstract RequestProcessor peek(String key);
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#remove(java.lang.String)
+	 */
+	public abstract RequestProcessor remove(String id);
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#evict()
+	 */
+	public abstract void evict();
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#isOffNode()
+	 */
+	public abstract boolean isOffNode();
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractMappedCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractMappedCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractMappedCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AbstractMappedCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,67 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.codehaus.wadi.sandbox.wcache.Cache;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public abstract class AbstractMappedCache extends AbstractCache {
+
+	protected final Map _map;
+
+	public AbstractMappedCache(Map map, Evicter evicter, Cache subcache) {
+		super(evicter, subcache);
+		_map=map;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#evict()
+	 */
+	public void evict() {
+		for (Iterator i=_map.entrySet().iterator(); i.hasNext();) {
+			Map.Entry e=(Map.Entry)i.next();
+			String key=(String)e.getKey();
+			RequestProcessor val=(RequestProcessor)e.getValue();
+			// TODO - we need an exclusive lock on entry before we try to evict (demote) it...
+			if (_evicter.evict(key, val)) {
+				_subcache.put(key, val);
+				i.remove();
+                if (_log.isInfoEnabled()) _log.info("demoted: " + key + " to " + _subcache);
+			}
+			// TODO - release exclusive lock here...
+		}
+	}
+
+	public String toString() {
+		return "<"+getClass().getName()+":"+_map.size()+">";
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AlwaysEvicter.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AlwaysEvicter.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AlwaysEvicter.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/AlwaysEvicter.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,43 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+import org.codehaus.wadi.sandbox.wcache.Cache.Evicter;
+
+/**
+ * @author jules
+ *
+ * Always choose to evict given entry
+ */
+public class AlwaysEvicter implements Evicter {
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache.Evicter#evict(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public boolean evict(String key, RequestProcessor val) {
+		// TODO Auto-generated method stub
+		return true;
+	}
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ClusterCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ClusterCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ClusterCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ClusterCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,78 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.codehaus.wadi.sandbox.wcache.Cache;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
+
+/**
+ * @author jules
+ *
+ * Promotion from this cache may result in some for of lazy remote reference.
+ * Demotion to this cache should result in a migration off-node.
+ *
+ * This tier is responsible for finding, caching and listening out for changes to the location of recently mobile content.
+ */
+public class ClusterCache extends AbstractMappedCache {
+
+	// TODO add ClusterListener for migrations - feed them into internal map
+	public ClusterCache(Evicter evicter, Cache subcache) {
+		super(new ConcurrentReaderHashMap(), evicter, subcache);
+		}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#put(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public RequestProcessor put(String key, RequestProcessor val) {
+		// TODO - check for relevant waiting get()s - wake them.
+		// do not raise notification, this will be done in migration code
+		return (RequestProcessor)_map.put(key, val);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#get(java.lang.String)
+	 */
+	public RequestProcessor get(String key) {
+		RequestProcessor val=peek(key);
+		// TODO - send message querying location to whole cluster - waiting, with timeout, for an update to our _map;
+		if (val==null)
+			val=promote(key, _subcache);
+		return val;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#remove(java.lang.String)
+	 */
+	public RequestProcessor remove(String key) {
+		// what should we do here ?
+		return (RequestProcessor)_map.remove(key);
+	}
+
+	public RequestProcessor peek(String key) {
+		return (RequestProcessor)_map.get(key);
+	}
+
+	public boolean isOffNode() {return true;}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InactiveEvicter.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InactiveEvicter.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InactiveEvicter.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InactiveEvicter.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,48 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+import org.codehaus.wadi.sandbox.wcache.Cache.Evicter;
+
+/**
+ * @author jules
+ *
+ * Choose to evict given entry if it is considered 'inactive'
+ */
+public class InactiveEvicter implements Evicter {
+	protected Log _log = LogFactory.getLog(InactiveEvicter.class);
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache.Evicter#evict(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public boolean evict(String key, RequestProcessor val) {
+	  boolean tmp=val.getTimeToLive()<10000;
+	  if (tmp) {
+            if (_log.isInfoEnabled()) _log.info("evicting due to lack of activity: " + key);
+	  }
+	  return tmp;
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InvalidEvicter.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InvalidEvicter.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InvalidEvicter.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/InvalidEvicter.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,42 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+import org.codehaus.wadi.sandbox.wcache.Cache.Evicter;
+
+/**
+ * @author jules
+ *
+ * Choose to evict given entry if it is 'invalid'
+ */
+public class InvalidEvicter implements Evicter {
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache.Evicter#evict(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public boolean evict(String key, RequestProcessor val) {
+		return val.getTimeToLive()<=0;// also need to test for invalidity - or id this the same thing ?
+	}
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/JDBCCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/JDBCCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/JDBCCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/JDBCCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,92 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.codehaus.wadi.sandbox.wcache.Cache;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+/**
+ * @author jules
+ *
+ * Promotion from this tier should result in content being loaded from JDBC
+ * Demotion to this tier should result in content being store via JDBC
+ */
+public class JDBCCache implements Cache {
+
+	protected final Evicter _evicter;
+	protected final Cache _subcache;
+
+	public JDBCCache(Evicter evicter, Cache subcache) {
+		_evicter=evicter;
+		_subcache=subcache;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#put(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public RequestProcessor put(String key, RequestProcessor rp) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#get(java.lang.String)
+	 */
+	public RequestProcessor get(String id) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#peek(java.lang.String)
+	 */
+	public RequestProcessor peek(String id) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#remove(java.lang.String)
+	 */
+	public RequestProcessor remove(String id) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#evict()
+	 */
+	public void evict() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache#isOffNode()
+	 */
+	public boolean isOffNode() {
+		// TODO Auto-generated method stub
+		return true;
+	}
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalDiscCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalDiscCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalDiscCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalDiscCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,134 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.ObjectOutput;
+
+import org.codehaus.wadi.SerializableContent;
+import org.codehaus.wadi.Streamer;
+import org.codehaus.wadi.sandbox.wcache.Cache;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author jules
+ *
+ * Promotion from this cache will result in the loading of content from local disc
+ * Demotion to this cache will result in the storing of content onto local disc.
+ * Assumptions are made about the exclusive ownership of the directory and files used.
+ * Content keys will be cached in memory, values on disc.
+ *
+ * This tier is intended as a disc spool for large amounts of frequently used content.
+ *
+ * This could return lazy references to on disc objects... consider...
+ */
+public class LocalDiscCache extends AbstractMappedCache {
+
+	protected File _dir;
+	protected Streamer _streamingStrategy;
+
+	public LocalDiscCache(File dir, Streamer streamingStrategy, Evicter evicter, Cache subcache) {
+		super(new ConcurrentHashMap(), evicter, subcache);
+	    assert dir.exists();
+	    assert dir.isDirectory();
+	    assert dir.canRead();
+	    assert dir.canWrite();
+	    _dir=dir;
+	    _streamingStrategy=streamingStrategy;
+	}
+
+	public RequestProcessor put(String key, RequestProcessor val) {
+		try
+		{
+			SerializableContent sc=val;
+			File file=new File(_dir, key.toString()+"."+_streamingStrategy.getSuffix());
+			ObjectOutput oos=_streamingStrategy.getOutputStream(new FileOutputStream(file));
+			sc.writeContent(oos);
+			oos.flush();
+			oos.close();
+
+			// do we need to worry about ttl ?
+			//	long willTimeOutAt=impl.getLastAccessedTime()+(impl.getMaxInactiveInterval()*1000);
+			//	file.setLastModified(willTimeOutAt);
+
+            if (_log.isInfoEnabled()) _log.info("stored (local disc): " + key + " : " + val);
+		}
+		catch (Exception e)
+		{
+            if (_log.isErrorEnabled()) _log.error("store (local disc) failed: " + key, e);
+		}
+
+		return (RequestProcessor)_map.put(key, val);
+	}
+
+	public RequestProcessor peek(String key) {
+//	    Object value=null;
+//
+//	    File file=new File(_dir, key.toString()+"."+_streamingStrategy.getSuffix());
+//	    if (file.exists())
+//	    {
+//	      try
+//	      {
+//		// SerializableContent sc=_valuePool.take();
+//	      	SerializableContent sc=new RequestProcessor(); // what are we going to do here - we need to decide how type chages as it is pro/demoted up stack...
+//		ObjectInput oi=_streamingStrategy.getInputStream(new FileInputStream(file));
+//		sc.readContent(oi);
+//		oi.close();
+//
+//		value=sc;
+//		_log.info("loaded (local disc): "+key+" : "+value);
+//	      }
+//	      catch (Exception e)
+//	      {
+//		_log.error("load (local disc) failed: "+key, e);
+//	      }
+//	    }
+//
+//	    //return value;
+		return (RequestProcessor)_map.get(key);
+		}
+
+	public RequestProcessor remove(String key) { // Aaargh - we don't want to return a value here - too costly... or can we get away with just two methods in a store ?
+//		   boolean success=false;
+//
+//		    try
+//		    {
+//		      File file=new File(_dir, key.toString()+"."+_streamingStrategy.getSuffix());
+//		      file.delete();
+//		      _log.info("removed (local disc): "+key);
+//		      success=true;
+//		    }
+//		    catch (Exception e)
+//		    {
+//		      _log.error("removal (local disc) failed: "+key, e);
+//		    }
+//
+//		    return success;
+		    return (RequestProcessor)_map.remove(key);
+		}
+
+	public boolean isOffNode() {return false;}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalRequestProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalRequestProcessor.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalRequestProcessor.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/LocalRequestProcessor.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,67 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class LocalRequestProcessor implements RequestProcessor {
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.RequestProcessor#process(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+	 */
+	public void process(ServletRequest req, ServletResponse res,
+			FilterChain chain) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public long getTimeToLive() {return 0;}//TODO
+	public void setTimeToLive(long ttl) {} //TODO
+
+	public int getMaxInactiveInterval() {return 0;}//TODO
+	public void setMaxInactiveInterval(int mii) {} //TODO
+
+	public void readContent(ObjectInput is)
+	    throws IOException, ClassNotFoundException {
+		// TODO
+	  }
+
+	public void writeContent(ObjectOutput os)
+	    throws IOException {
+		// TODO
+	  }
+	}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MaxInactiveIntervalEvicter.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MaxInactiveIntervalEvicter.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MaxInactiveIntervalEvicter.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MaxInactiveIntervalEvicter.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,49 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+import org.codehaus.wadi.sandbox.wcache.Cache.Evicter;
+
+/**
+ * @author jules
+ *
+ * Choose to evict given entry if it has remained inactive for more than a than a given Max-Inactive-Interval
+ */
+public class MaxInactiveIntervalEvicter implements Evicter {
+	protected Log _log = LogFactory.getLog(MaxInactiveIntervalEvicter.class);
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache.Evicter#evict(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public boolean evict(String key, RequestProcessor val) {
+		boolean tmp=val.getTimeToLive()<=0;
+		if (tmp) {
+            if (_log.isInfoEnabled()) _log.info("evicting due to total inactivity: " + key);
+        }
+		return tmp;
+	}
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MemoryCache.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MemoryCache.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MemoryCache.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/MemoryCache.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,49 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.sandbox.wcache.Cache;
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
+
+/**
+ * @author jules
+ *
+ * A Map of content in local memory. Exclusive access to the map is assumed.
+ */
+public class MemoryCache extends AbstractMappedCache {
+	protected static final Log _log = LogFactory.getLog(MemoryCache.class);
+
+	public MemoryCache(Evicter evicter, Cache subcache) {
+		super(new ConcurrentReaderHashMap(), evicter, subcache);
+	}
+
+	public RequestProcessor put(String key, RequestProcessor val){return (RequestProcessor)_map.put(key, val);}
+	public RequestProcessor peek(String key) {return (RequestProcessor)_map.get(key);}
+	public RequestProcessor remove(String key) {return (RequestProcessor)_map.remove(key);}
+
+	public boolean isOffNode() {return false;}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/NeverEvicter.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/NeverEvicter.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/NeverEvicter.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/NeverEvicter.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,43 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+import org.codehaus.wadi.sandbox.wcache.Cache.Evicter;
+
+/**
+ * @author jules
+ *
+ * Never choose to evict given entry.
+ */
+public class NeverEvicter implements Evicter {
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.Cache.Evicter#evict(java.lang.String, org.codehaus.wadi.test.cache.RequestProcessor)
+	 */
+	public boolean evict(String key, RequestProcessor val) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ProxyRequestProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ProxyRequestProcessor.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ProxyRequestProcessor.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/sandbox/wcache/impl/ProxyRequestProcessor.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,67 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.
+ */
+/*
+ * Created on Feb 14, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.codehaus.wadi.sandbox.wcache.impl;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.codehaus.wadi.sandbox.wcache.RequestProcessor;
+
+/**
+ * @author jules
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class ProxyRequestProcessor implements RequestProcessor {
+
+	/* (non-Javadoc)
+	 * @see org.codehaus.wadi.test.cache.RequestProcessor#process(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+	 */
+	public void process(ServletRequest req, ServletResponse res,
+			FilterChain chain) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public long getTimeToLive() {return 0;}// TODO
+	public void setTimeToLive(long ttl) {} // TODO
+
+	public int getMaxInactiveInterval() {return 0;}//TODO
+	public void setMaxInactiveInterval(int mii) {} //TODO
+
+	public void readContent(ObjectInput is)
+	    throws IOException, ClassNotFoundException {
+		// TODO
+	  }
+
+	public void writeContent(ObjectOutput os)
+	    throws IOException {
+		// TODO
+	  }
+	}