some serious new feature implementation:
- cookie-based persistent logins - expanded activity reporting - "top" and "fixed" left menus are now dynamically generated from XML config, not hard coded - error reporting enhanced and protection increased - "About Venice" page first draft - new means of "framing" static content within the Venice "frame" - base page now includes the "footer" itself, "content" pages don't anymore - general cleanup of some heavyweight old containers, replaced with faster Collections framework containers - probably more, there's a LOT of stuff in here
This commit is contained in:
400
src/com/silverwrist/util/cachemap/CacheMap.java
Normal file
400
src/com/silverwrist/util/cachemap/CacheMap.java
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (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.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.util.cachemap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class CacheMap implements Map
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Internal class used to do comparisons for cache shrinkage
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static class CacheOrdering implements Comparator
|
||||
{
|
||||
private CacheMapStrategy strategy; // CacheMap's strategy object
|
||||
private long tick; // when the sort operation started
|
||||
|
||||
CacheOrdering(CacheMapStrategy strategy)
|
||||
{
|
||||
this.strategy = strategy;
|
||||
this.tick = System.currentTimeMillis();
|
||||
|
||||
} // end constructor
|
||||
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
long figm1 = strategy.getEntryValue((CacheMapEntry)o1,tick);
|
||||
long figm2 = strategy.getEntryValue((CacheMapEntry)o2,tick);
|
||||
return (int)(figm1 - figm2); // we want the largest figures of merit to go first
|
||||
|
||||
} // end compare
|
||||
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return (o instanceof CacheOrdering);
|
||||
|
||||
} // end equals
|
||||
|
||||
} // end class CacheOrdering
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Internal class implementing a default cache ordering strategy
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static class DefaultStrategy implements CacheMapStrategy
|
||||
{
|
||||
private static final long SCALING_FACTOR = 5000;
|
||||
|
||||
DefaultStrategy()
|
||||
{ // do nothing
|
||||
} // end constructor
|
||||
|
||||
public long getEntryValue(CacheMapEntry entry, long tick)
|
||||
{
|
||||
return (entry.getHits() * SCALING_FACTOR) - entry.getAge(tick);
|
||||
|
||||
} // end getEntryValue
|
||||
|
||||
} // end class DefaultStrategy
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Static data members
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static final DefaultStrategy default_strategy_singleton = new DefaultStrategy();
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private int capacity; // capacity of the CacheMap
|
||||
private int shrink_percentage; // what percentage we shrink by when full
|
||||
private CacheMapStrategy strategy; // strategy routine to use to purge entries
|
||||
private HashMap base_map; // maps keys to CacheMapEntry values
|
||||
private ArrayList element_list; // the actual elements
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructors
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public CacheMap(int capacity, int shrink_percentage, CacheMapStrategy strategy)
|
||||
{
|
||||
if (capacity<=0)
|
||||
throw new IllegalArgumentException("capacity must be greater than 0");
|
||||
if ((shrink_percentage<=0) || (shrink_percentage>100))
|
||||
throw new IllegalArgumentException("shrink_percentage must be in [1, 100]");
|
||||
if (strategy==null)
|
||||
throw new NullPointerException("no strategy passed to CacheMap");
|
||||
|
||||
this.capacity = capacity;
|
||||
this.shrink_percentage = shrink_percentage;
|
||||
this.strategy = strategy;
|
||||
this.base_map = new HashMap(10);
|
||||
this.element_list = new ArrayList(10);
|
||||
|
||||
} // end constructor
|
||||
|
||||
public CacheMap(int capacity, int shrink_percentage)
|
||||
{
|
||||
this(capacity,shrink_percentage,default_strategy_singleton);
|
||||
|
||||
} // end constructor
|
||||
|
||||
public CacheMap(int capacity)
|
||||
{
|
||||
this(capacity,10,default_strategy_singleton);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface Map
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public int size()
|
||||
{
|
||||
return base_map.size();
|
||||
|
||||
} // end size
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return base_map.isEmpty();
|
||||
|
||||
} // end isEmpty
|
||||
|
||||
public boolean containsKey(Object key)
|
||||
{
|
||||
return base_map.containsKey(key);
|
||||
|
||||
} // end containsKey
|
||||
|
||||
public boolean containsValue(Object value)
|
||||
{
|
||||
Iterator it = element_list.iterator();
|
||||
while (it.hasNext())
|
||||
{ // look at all the CacheMapEntry values we have
|
||||
CacheMapEntry cme = (CacheMapEntry)(it.next());
|
||||
Object my_val = cme.getValue();
|
||||
if (my_val==null)
|
||||
{ // test for also null
|
||||
if (value==null)
|
||||
return true;
|
||||
|
||||
} // end if
|
||||
else
|
||||
{ // make sure the other value is non-null before we test equality
|
||||
if ((value!=null) && my_val.equals(value))
|
||||
return true;
|
||||
|
||||
} // end else
|
||||
|
||||
} // end while
|
||||
|
||||
return false; // nope, sorry
|
||||
|
||||
} // end containsValue
|
||||
|
||||
public Object get(Object key)
|
||||
{
|
||||
CacheMapEntry cme = (CacheMapEntry)(base_map.get(key));
|
||||
if (cme==null)
|
||||
return null;
|
||||
cme.touch();
|
||||
return cme.getValue();
|
||||
|
||||
} // end get
|
||||
|
||||
public Object put(Object key, Object value)
|
||||
{
|
||||
Object rc = null;
|
||||
CacheMapEntry cme = (CacheMapEntry)(base_map.get(key));
|
||||
if (cme==null)
|
||||
{ // create a new CacheMapEntry for this key
|
||||
cme = new CacheMapEntry(key,value);
|
||||
|
||||
synchronized (this)
|
||||
{ // insert it into the basic object
|
||||
if (base_map.size()==capacity)
|
||||
shrink();
|
||||
element_list.add(cme);
|
||||
base_map.put(cme.getKey(),cme);
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
} // end if
|
||||
else
|
||||
{ // we have an old value - replace it and touch the entry
|
||||
cme.touch();
|
||||
rc = cme.setValue(value);
|
||||
|
||||
} // end else
|
||||
|
||||
return rc;
|
||||
|
||||
} // end put
|
||||
|
||||
public Object remove(Object key)
|
||||
{
|
||||
Object rc = null;
|
||||
CacheMapEntry cme = (CacheMapEntry)(base_map.get(key));
|
||||
if (cme!=null)
|
||||
{ // save the mapped value before we remove it
|
||||
rc = cme.getValue();
|
||||
|
||||
synchronized (this)
|
||||
{ // remove the values
|
||||
base_map.remove(key);
|
||||
element_list.remove(cme);
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
} // end if
|
||||
|
||||
return rc;
|
||||
|
||||
} // end remove
|
||||
|
||||
public void putAll(Map map)
|
||||
{
|
||||
synchronized (this)
|
||||
{ // make sure we have enough space in the CacheMap for all the new elements!
|
||||
while ((map.size() + base_map.size()) > capacity)
|
||||
shrink();
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
Iterator it = map.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // add each element in turn
|
||||
Map.Entry me = (Map.Entry)(it.next());
|
||||
put(me.getKey(),me.getValue());
|
||||
|
||||
} // end while
|
||||
|
||||
} // end putAll
|
||||
|
||||
public synchronized void clear()
|
||||
{
|
||||
base_map.clear();
|
||||
element_list.clear();
|
||||
|
||||
} // end clear
|
||||
|
||||
public Set keySet()
|
||||
{
|
||||
return base_map.keySet();
|
||||
|
||||
} // end keySet
|
||||
|
||||
public Collection values()
|
||||
{
|
||||
return null; // not implemented
|
||||
|
||||
} // end values
|
||||
|
||||
public Set entrySet()
|
||||
{
|
||||
return null; // not implemented
|
||||
|
||||
} // end entrySet
|
||||
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if ((o==null) || !(o instanceof Map))
|
||||
return false; // not a map
|
||||
Map other = (Map)o;
|
||||
if (other.size()!=base_map.size())
|
||||
return false; // size does matter!
|
||||
Iterator it = base_map.values().iterator();
|
||||
while (it.hasNext())
|
||||
{ // get each of the entries out and use that to do a key-value comparison
|
||||
CacheMapEntry cme = (CacheMapEntry)(it.next());
|
||||
Object o1 = cme.getValue();
|
||||
Object o2 = other.get(cme.getKey());
|
||||
if (o1==null)
|
||||
{ // must have a matching null
|
||||
if (o2!=null)
|
||||
return false;
|
||||
|
||||
} // end if
|
||||
else
|
||||
{ // make sure we have a matching object (not null)
|
||||
if ((o2==null) || !(o2.equals(o1)))
|
||||
return false;
|
||||
|
||||
} // end else
|
||||
|
||||
} // end while
|
||||
|
||||
return true; // all OK!
|
||||
|
||||
} // end equals
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int rc = 0;
|
||||
Iterator it = base_map.values().iterator();
|
||||
while (it.hasNext())
|
||||
{ // add up the hash codes and return them
|
||||
CacheMapEntry cme = (CacheMapEntry)(it.next());
|
||||
rc += cme.hashCode();
|
||||
|
||||
} // end while
|
||||
|
||||
return rc;
|
||||
|
||||
} // end hashCode
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External getters/setters
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public int getCapacity()
|
||||
{
|
||||
return capacity;
|
||||
|
||||
} // end getCapacity
|
||||
|
||||
public void setCapacity(int c)
|
||||
{
|
||||
if (c<=0)
|
||||
throw new IllegalArgumentException("capacity must be greater than 0");
|
||||
capacity = c;
|
||||
|
||||
} // end setCapacity
|
||||
|
||||
public int getShrinkPercentage()
|
||||
{
|
||||
return shrink_percentage;
|
||||
|
||||
} // end getShrinkPercentage
|
||||
|
||||
public void setShrinkPercentage(int p)
|
||||
{
|
||||
if ((p<=0) || (p>100))
|
||||
throw new IllegalArgumentException("shrink_percentage must be in [1, 100]");
|
||||
shrink_percentage = p;
|
||||
|
||||
} // end setShrinkPercentage
|
||||
|
||||
public CacheMapStrategy getStrategy()
|
||||
{
|
||||
return strategy;
|
||||
|
||||
} // end getStrategy
|
||||
|
||||
public void setStrategy(CacheMapStrategy s)
|
||||
{
|
||||
if (s==null)
|
||||
throw new NullPointerException("no strategy passed to CacheMap");
|
||||
strategy = s;
|
||||
|
||||
} // end setStrategy
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public synchronized void shrink()
|
||||
{
|
||||
// Figure out how many elements to remove.
|
||||
int num_remove = (element_list.size() * shrink_percentage) / 100;
|
||||
|
||||
// Sort the element list to figure out which elements to remove.
|
||||
Collections.sort(element_list,new CacheOrdering(strategy));
|
||||
|
||||
// The elements we want to remove are at the end of the array, so start from there.
|
||||
for (int i=0; i<num_remove; i++)
|
||||
{ // remove the "removed" entries from the hash map
|
||||
CacheMapEntry cme = (CacheMapEntry)(element_list.remove(element_list.size() - 1));
|
||||
base_map.remove(cme.getKey());
|
||||
|
||||
} // end for
|
||||
|
||||
} // end shrink
|
||||
|
||||
} // end class CacheMap
|
||||
154
src/com/silverwrist/util/cachemap/CacheMapEntry.java
Normal file
154
src/com/silverwrist/util/cachemap/CacheMapEntry.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (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.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.util.cachemap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class CacheMapEntry implements Map.Entry
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private Object key;
|
||||
private Object value;
|
||||
private int hits = 0;
|
||||
private long timestamp;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
CacheMapEntry(Object key, Object value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* finalize() function
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
protected void finalize()
|
||||
{
|
||||
key = null;
|
||||
value = null;
|
||||
|
||||
} // end finalize
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface MapEntry
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public final Object getKey()
|
||||
{
|
||||
return key;
|
||||
|
||||
} // end getKey
|
||||
|
||||
public final Object getValue()
|
||||
{
|
||||
return value;
|
||||
|
||||
} // end getValue
|
||||
|
||||
public final Object setValue(Object o)
|
||||
{
|
||||
Object rc = value;
|
||||
value = o;
|
||||
return rc;
|
||||
|
||||
} // end setValue
|
||||
|
||||
public final boolean equals(Object o)
|
||||
{
|
||||
// make sure the other element is a Map.Entry
|
||||
if ((o==null) || !(o instanceof Map.Entry))
|
||||
return false;
|
||||
Map.Entry other = (Map.Entry)o;
|
||||
|
||||
// compare the keys
|
||||
if (key==null)
|
||||
{ // the other key must be null
|
||||
if (other.getKey()!=null)
|
||||
return false;
|
||||
|
||||
} // end if
|
||||
else
|
||||
{ // the other key must be equal to us
|
||||
if ((other.getKey()==null) || (!(key.equals(other.getKey()))))
|
||||
return false;
|
||||
|
||||
} // end else
|
||||
|
||||
// compare the values
|
||||
if (value==null)
|
||||
return (other.getValue()==null);
|
||||
else
|
||||
return ((other.getValue()!=null) && value.equals(other.getValue()));
|
||||
|
||||
} // end equals
|
||||
|
||||
public final int hashCode()
|
||||
{
|
||||
int rc = 0;
|
||||
if (key!=null)
|
||||
rc ^= key.hashCode();
|
||||
if (value!=null)
|
||||
rc ^= value.hashCode();
|
||||
return rc;
|
||||
|
||||
} // end hashCode
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
final int getHits()
|
||||
{
|
||||
return hits;
|
||||
|
||||
} // end getHits
|
||||
|
||||
final long getTimestamp()
|
||||
{
|
||||
return timestamp;
|
||||
|
||||
} // end getTimestamp
|
||||
|
||||
final long getAge(long tick)
|
||||
{
|
||||
return (tick - timestamp);
|
||||
|
||||
} // end getAge
|
||||
|
||||
final void touch()
|
||||
{
|
||||
hits++;
|
||||
timestamp = System.currentTimeMillis();
|
||||
|
||||
} // end touch
|
||||
|
||||
} // end class CacheMapEntry
|
||||
24
src/com/silverwrist/util/cachemap/CacheMapStrategy.java
Normal file
24
src/com/silverwrist/util/cachemap/CacheMapStrategy.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (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.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.util.cachemap;
|
||||
|
||||
public interface CacheMapStrategy
|
||||
{
|
||||
public abstract long getEntryValue(CacheMapEntry entry, long tick);
|
||||
|
||||
} // end interface CacheMapStrategy
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (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.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.util.collections;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ReadOnlyVector extends AbstractList
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private Vector my_vec; // local vector
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public ReadOnlyVector(Vector vec)
|
||||
{
|
||||
my_vec = vec;
|
||||
my_vec.trimToSize();
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* finalize() method
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
my_vec = null;
|
||||
super.finalize();
|
||||
|
||||
} // end finalize
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from superclass AbstractList
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public Object get(int index)
|
||||
{
|
||||
return my_vec.elementAt(index);
|
||||
|
||||
} // end get
|
||||
|
||||
public int size()
|
||||
{
|
||||
return my_vec.size();
|
||||
|
||||
} // end size
|
||||
|
||||
} // end class ReadOnlyVector
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.silverwrist.util.rcache;
|
||||
|
||||
import java.util.*;
|
||||
import com.silverwrist.util.collections.*;
|
||||
|
||||
public class ReferenceCache
|
||||
{
|
||||
@@ -124,7 +123,7 @@ public class ReferenceCache
|
||||
|
||||
public List sweepReturn()
|
||||
{
|
||||
Vector rc = new Vector();
|
||||
ArrayList rc = new ArrayList();
|
||||
int count = 0;
|
||||
|
||||
synchronized (this)
|
||||
@@ -155,7 +154,7 @@ public class ReferenceCache
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
return new ReadOnlyVector(rc);
|
||||
return Collections.unmodifiableList(rc);
|
||||
|
||||
} // end sweepReturn
|
||||
|
||||
|
||||
Reference in New Issue
Block a user