[jboss-cvs] JBossCache/src/org/jboss/cache/pojo/collection ...
Ben Wang
bwang at jboss.com
Sat Jan 13 10:55:06 EST 2007
User: bwang
Date: 07/01/13 10:55:06
Added: src/org/jboss/cache/pojo/collection
CollectionInterceptorUtil.java CachedListImpl.java
CachedSetImpl.java CachedListAbstract.java
IntegerCache.java CachedMapImpl.java
Log:
JBCACHE-922 Merged src-50 and tests-50 into src and tests, respectively.
Revision Changes Path
1.1 date: 2007/01/13 15:55:05; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java
Index: CollectionInterceptorUtil.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.aop.AspectManager;
import org.jboss.aop.InstanceAdvisor;
import org.jboss.aop.advice.AdviceBinding;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;
import org.jboss.aop.pointcut.ast.ParseException;
import org.jboss.aop.proxy.ClassProxy;
import org.jboss.aop.proxy.ClassProxyFactory;
import org.jboss.aop.util.MethodHashing;
import org.jboss.cache.Fqn;
import org.jboss.cache.pojo.PojoCacheException;
import org.jboss.cache.pojo.impl.PojoCacheImpl;
import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
import org.jboss.cache.pojo.interceptors.dynamic.CachedListInterceptor;
import org.jboss.cache.pojo.interceptors.dynamic.CachedMapInterceptor;
import org.jboss.cache.pojo.interceptors.dynamic.CachedSetInterceptor;
import org.jboss.cache.pojo.interceptors.dynamic.ReentrancyStopperInterceptor;
import org.jboss.cache.pojo.util.AopUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* CollectionInterceptorUtil contains helper methods for the interceptors of
* the different collection types.
*
* @author <a href="mailto:harald at gliebe.de">Harald Gliebe</a>
* @author Ben Wang
*/
public class CollectionInterceptorUtil
{
private static Log log = LogFactory.getLog(CollectionInterceptorUtil.class.getName());
private static ClassProxy createProxy(Class clazz, AbstractCollectionInterceptor interceptor)
throws Exception
{
ClassProxy result = ClassProxyFactory.newInstance(clazz);
InstanceAdvisor advisor = result._getInstanceAdvisor();
advisor.appendInterceptor(interceptor);
// Also take care of just toString()
try
{
String bindName = clazz.getName() + ".toString";
HashMap<String, AdviceBinding> bindings = AspectManager.instance().getBindings();
if (bindings.get(bindName) == null)
{
String bind = null;
if (interceptor instanceof CachedListInterceptor)
{
bind = "execution(public String " + CachedListAbstract.class.getName() + "->toString())";
} else if (interceptor instanceof CachedSetInterceptor)
{
bind = "execution(public String " + CachedSetImpl.class.getName() + "->toString())";
} else if (interceptor instanceof CachedMapInterceptor)
{
bind = "execution(public String " + CachedMapImpl.class.getName() + "->toString())";
} else
{
throw new IllegalStateException("CollectionInterceptorUtil.createProxy(). Non Collection interceptor"
+ interceptor);
}
AdviceBinding bindingm = new AdviceBinding(bindName,
bind, null);
bindingm.addInterceptor(ReentrancyStopperInterceptor.class);
AspectManager.instance().addBinding(bindingm);
// result._getInstanceAdvisor().addBinding(bindingm);
}
}
catch (ParseException e)
{
throw new PojoCacheException("PojoUtil._attachInterceptor(): can't parse the field binding: "
+ e);
}
return result;
}
public static ClassProxy createMapProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, Map obj) throws Exception
{
return CollectionInterceptorUtil.createProxy(clazz, new CachedMapInterceptor(cache, fqn, clazz, obj));
}
public static ClassProxy createListProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, List obj) throws Exception
{
return CollectionInterceptorUtil.createProxy(clazz, new CachedListInterceptor(cache, fqn, clazz, obj));
}
public static ClassProxy createSetProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, Set obj) throws Exception
{
return CollectionInterceptorUtil.createProxy(clazz, new CachedSetInterceptor(cache, fqn, clazz, obj));
}
public static AbstractCollectionInterceptor getInterceptor(ClassProxy proxy)
{
InstanceAdvisor advisor = proxy._getInstanceAdvisor();
return (AbstractCollectionInterceptor) AopUtil.findCollectionInterceptor(advisor);
}
public static Map getMethodMap(Class clazz)
{
Map result = ClassProxyFactory.getMethodMap(clazz.getName());
if (result == null)
{
try
{
ClassProxyFactory.newInstance(clazz);
}
catch (Exception e)
{
throw new PojoCacheException(e);
}
result = ClassProxyFactory.getMethodMap(clazz.getName());
}
return result;
}
public static Map getManagedMethods(Class clazz)
{
Method tostring = null;
try
{
tostring = Object.class.getDeclaredMethod("toString", new Class[0]);
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
throw new PojoCacheException("getManagedMathods: " + e);
}
Map managedMethods = new HashMap();
try
{
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++)
{
long hash = MethodHashing.methodHash(methods[i]);
managedMethods.put(hash, methods[i]);
}
// Add toString to ManagedMethod
long hash = MethodHashing.methodHash(tostring);
managedMethods.put(hash, tostring);
}
catch (Exception ignored)
{
ignored.printStackTrace();
}
return managedMethods;
}
public static Object invoke(Invocation invocation,
Object interceptor,
Map methodMap,
Map managedMethods)
throws Throwable
{
try
{
if (invocation instanceof MethodInvocation)
{
MethodInvocation methodInvocation = (MethodInvocation) invocation;
Long methodHash = methodInvocation.getMethodHash();
Method method = (Method) managedMethods.get(methodHash);
if (log.isTraceEnabled() && method != null)
{
log.trace("invoke(): method intercepted " + method.getName());
}
Object[] args = methodInvocation.getArguments();
if (method != null)
{
return method.invoke(interceptor, args);
} else
{
method = methodInvocation.getMethod();
if (method == null)
{
method = (Method) methodMap.get(methodHash);
}
if (log.isTraceEnabled())
log.trace("invoke(): non-managed method: " + method.toString());
Object target = methodInvocation.getTargetObject();
if (target == null)
{
throw new PojoCacheException("CollectionInterceptorUtil.invoke(): targetObject is null." +
" Can't invoke " + method.toString());
}
return method.invoke(target, args);
// return method.invoke(interceptor, args);
}
}
}
catch (InvocationTargetException e)
{
if (e.getCause() != null)
throw e.getCause();
else if (e.getTargetException() != null)
throw e.getTargetException();
throw e;
}
return invocation.invokeNext();
}
}
1.1 date: 2007/01/13 15:55:05; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/collection/CachedListImpl.java
Index: CachedListImpl.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.pojo.impl.PojoCacheImpl;
import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
import org.jboss.cache.pojo.util.AopUtil;
import org.jboss.cache.pojo.util.CacheApiUtil;
import org.jboss.cache.pojo.util.Null;
import java.io.ObjectStreamException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* List implementation that uses cache as a backend store.
*
* @author Ben Wang
* @author Scott Marlow
*/
public class CachedListImpl extends CachedListAbstract
{
private static Log log_ = LogFactory.getLog(CachedListImpl.class.getName());
private CacheSPI cache_;
private PojoCacheImpl pCache_;
private AbstractCollectionInterceptor interceptor_;
public CachedListImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
{
pCache_ = cache;
cache_ = (CacheSPI) pCache_.getCache();
interceptor_ = interceptor;
}
private Fqn getFqn()
{
return interceptor_.getFqn();
}
// implementation of the java.util.List interface
private Set<Node> getNodeChildren()
{
return CacheApiUtil.getNodeChildren(cache_, getFqn());
}
/**
* Serialize a normal ArrayList
*/
private Object XwriteReplace() throws ObjectStreamException
{
log_.warn("writeReplace(): this calss is not suppored to be serialized." +
" Will substitue with a normal ArryList");
ArrayList toSerialize = new ArrayList();
toSerialize.addAll(this);
return toSerialize;
}
public Object get(int index)
{
checkIndex();
return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
}
private static void checkIndex()
{
// TODO This is too expensive now to check it everytime from the cache (potentially twice).
// It is showing up in the JProfiler. So I am disabling it now.
return;
/*
if(size() == 0) return; // No need to check here.
if( i < 0 || i >= size() ) {
throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " +i
+ " but size is " +size());
} */
}
public int size()
{
Set<Node> children = getNodeChildren();
return children == null ? 0 : children.size();
}
public Object set(int index, Object element)
{
if (index != 0)
checkIndex(); // Since index can be size().
return Null.toNullValue(pCache_.attach(AopUtil.constructFqn(getFqn(),
IntegerCache.toString(index)), Null.toNullObject(element)));
}
public void add(int index, Object element)
{
if (index != 0)
checkIndex(); // Since index can be size().
for (int i = size(); i > index; i--)
{
Object obj = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i - 1)));
pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i)), obj);
}
pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index)), Null.toNullObject(element));
}
public int indexOf(Object o)
{
int size = size();
if (o == null)
{
for (int i = 0; i < size; i++)
{
if (null == get(i))
return i;
}
} else
{
for (int i = 0; i < size; i++)
{
if (o.equals(get(i)))
return i;
}
}
return -1;
}
public int lastIndexOf(Object o)
{
if (o == null)
{
for (int i = size() - 1; i >= 0; i--)
{
if (null == get(i))
return i;
}
} else
{
for (int i = size() - 1; i >= 0; i--)
{
if (o.equals(get(i)))
return i;
}
}
return -1;
}
public Object remove(int index)
{
checkIndex();
// Object result = cache.removeObject(((Fqn) fqn.clone()).add(new Integer(index)));
int size = size();
Object result = Null.toNullValue(pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
if (size == (index + 1))
{
return result; // We are the last one.
}
for (int i = index; i < size - 1; i++)
{
Object obj = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i + 1)));
pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i)), obj);
}
return result;
}
public Iterator iterator()
{
// TODO: check for concurrent modification
return new Iterator()
{
// Need to share this
int current = -1;
int size = size();
public boolean hasNext()
{
if (size == 0) return false;
if (current > size)
throw new NoSuchElementException("CachedSetImpl.iterator.hasNext(). " +
" Cursor position " + current + " is greater than the size " + size());
return current < size - 1;
}
public Object next()
{
if (current == size)
throw new NoSuchElementException("CachedSetImpl.iterator.next(). " +
" Cursor position " + current + " is greater than the size " + size());
return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(++current))));
}
public void remove()
{
// TODO Need optimization here since set does not care about index
if (size == 0) return;
if (current == size)
throw new IllegalStateException("CachedSetImpl.iterator.remove(). " +
" Cursor position " + current + " is greater than the size " + size);
if (current < (size - 1))
{
// Need to reshuffle the items.
Object last = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(current)));
for (int i = current + 1; i < size; i++)
{
last = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i)));
pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i - 1)), last);
}
} else
{ // we are the last index.
// Need to move back the cursor.
pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(current)));
}
current--;
size--;
}
};
}
public List subList(int fromIndex, int toIndex)
{
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
if (fromIndex == toIndex) // request for empty list?
return new LinkedList();
return new MyCachedSubListImpl(this, fromIndex, toIndex);
}
public ListIterator listIterator()
{
return new MyListIterator(this, 0);
}
public ListIterator listIterator(int index)
{
return new MyListIterator(this, index);
}
static class MyListIterator implements ListIterator
{
int index = 0;
List list_;
public MyListIterator(List list, int index)
{
list_ = list;
if (index < 0 || index > list_.size())
{
throw new IndexOutOfBoundsException("CachedListImpl: MyListIterator construction. " +
" Index is out of bound : " + index);
}
this.index = index;
}
public int nextIndex()
{
return index;
}
public int previousIndex()
{
return index - 1;
}
public void remove()
{
int size = list_.size();
if (size == 0) return;
if (previousIndex() == size)
throw new IllegalStateException("CachedSetImpl.MyListIterator.remove(). " +
" Cursor position " + index + " is greater than the size " + size);
if (previousIndex() < (size))
{
list_.remove(previousIndex());
index--;
}
}
public boolean hasNext()
{
return (index < list_.size());
}
public boolean hasPrevious()
{
return (index != 0);
}
public Object next()
{
if (index == list_.size())
throw new NoSuchElementException();
index++;
return list_.get(index - 1); // pass zero relative index
}
public Object previous()
{
if (index == 0)
throw new NoSuchElementException();
index--;
return list_.get(index);
}
public void add(Object o)
{
int size = list_.size();
if (size == 0) return;
if (previousIndex() == size)
throw new IllegalStateException("CachedSetImpl.MyListIterator.add(). " +
" Cursor position " + index + " is greater than the size " + size);
if (previousIndex() < (size))
{
list_.add(previousIndex(), o);
}
}
public void set(Object o)
{
int size = list_.size();
if (size == 0) return;
if (previousIndex() == size)
throw new IllegalStateException("CachedSetImpl.MyListIterator.set(). " +
" Cursor position " + index + " is greater than the size " + size);
if (previousIndex() < (size))
{
list_.set(previousIndex(), o);
}
}
}
static public class MyCachedSubListImpl extends CachedListAbstract implements List
{
private List backStore_;
private int fromIndex_;
private int toIndex_;
MyCachedSubListImpl(List backStore, int fromIndex, int toIndex)
{
backStore_ = backStore;
fromIndex_ = fromIndex;
toIndex_ = toIndex;
}
public int size()
{
int size = backStore_.size();
if (size > toIndex_)
size = toIndex_;
size -= fromIndex_; // subtract number of items ignored at the start of list
return size;
}
public Iterator iterator()
{
// TODO: check for concurrent modification
return new Iterator()
{
int current = -1;
Iterator iter_ = initializeIter();
private Iterator initializeIter()
{
Iterator iter = backStore_.iterator();
for (int looper = 0; looper < fromIndex_; looper++)
if (iter.hasNext()) // skip past to where we need to start from
iter.next();
return iter;
}
public boolean hasNext()
{
int size = size();
if (size == 0) return false;
if (current > size)
throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.hasNext(). " +
" Cursor position " + current + " is greater than the size " + size());
return current < size() - 1;
}
public Object next()
{
if (current == size())
throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.next(). " +
" Cursor position " + current + " is greater than the size " + size());
current++;
return iter_.next();
}
public void remove()
{
iter_.remove();
current--;
}
};
}
public Object get(int index)
{
checkIndex(index);
return backStore_.get(index + fromIndex_);
}
public Object set(int index, Object element)
{
checkIndex(index);
return backStore_.set(index + fromIndex_, element);
}
public void add(int index, Object element)
{
backStore_.add(index + fromIndex_, element);
}
public Object remove(int index)
{
return backStore_.remove(index + fromIndex_);
}
public int indexOf(Object o)
{
int index = backStore_.indexOf(o);
if (index < fromIndex_ || index >= toIndex_)
index = -1;
else
index -= fromIndex_; // convert to be relative to our from/to range
return index;
}
public int lastIndexOf(Object o)
{
int index = backStore_.lastIndexOf(o);
if (index < fromIndex_ || index >= toIndex_)
index = -1;
else
index -= fromIndex_; // convert to be relative to our from/to range
return index;
}
public ListIterator listIterator()
{
return new MyListIterator(this, 0);
}
public ListIterator listIterator(int index)
{
return new MyListIterator(this, index);
}
public List subList(int fromIndex, int toIndex)
{
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
if (fromIndex == toIndex) // request for empty list?
return new LinkedList();
return new MyCachedSubListImpl(this, fromIndex, toIndex);
}
private void checkIndex(int i)
{
if (size() == 0) return; // No need to check here.
if (i < 0 || i >= size())
{
throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " + i
+ " but size is " + size());
}
}
}
}
1.1 date: 2007/01/13 15:55:05; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/collection/CachedSetImpl.java
Index: CachedSetImpl.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.collection;
import org.jboss.cache.CacheException;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.pojo.annotation.Reentrant;
import org.jboss.cache.pojo.impl.PojoCacheImpl;
import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
import org.jboss.cache.pojo.util.AopUtil;
import org.jboss.cache.pojo.util.CacheApiUtil;
import org.jboss.cache.pojo.util.Null;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Set implementation that uses a cache as an underlying backend store.
* Set data is stored in children nodes named based on the attached Object's hash code
* in hexidecimal string form.
* If there are conflicts between two Objects with the same hash code, then a
* counter (upper 32 bits of 64) is used.
*
* @author Ben Wang
* @author Scott Marlow
* @author Jussi Pyorre
*/
@Reentrant
public class CachedSetImpl extends AbstractSet
{
// protected static final Log log_=LogFactory.getLog(CachedSetImpl.class);
private PojoCacheImpl pCache_;
private CacheSPI cache_;
private AbstractCollectionInterceptor interceptor_;
public CachedSetImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
{
pCache_ = cache;
this.cache_ = (CacheSPI) pCache_.getCache();
this.interceptor_ = interceptor;
}
private Set<Node> getNodeChildren()
{
return CacheApiUtil.getNodeChildren(cache_, getFqn());
}
private Fqn getFqn()
{
// Cannot cache this as this can be reset
return interceptor_.getFqn();
}
// java.util.Set implementation
public boolean add(Object o)
{
o = Null.toNullObject(o);
int hashCode = o.hashCode();
int size = size();
for (int i = 0; i < size + 1; i++)
{
Object key = toLong(hashCode, i);
Object o2 = getNoUnmask(key);
if (o2 == null)
{
attachNoMask(key, o);
return true;
}
if (o.equals(o2))
{
return false;
}
}
// should never reach here
throw new CacheException();
}
public void clear()
{
Set<Node> children = getNodeChildren();
for (Node n : children)
{
pCache_.detach(n.getFqn());
}
}
public boolean contains(Object o)
{
o = Null.toNullObject(o);
int hashCode = o.hashCode();
int size = size();
for (int i = 0; i < size; i++)
{
Object key = toLong(hashCode, i);
Object o2 = getNoUnmask(key);
if (o2 == null)
{
return false;
}
if (o.equals(o2))
{
return true;
}
}
return false;
}
public Iterator iterator()
{
Node node = cache_.getRoot().getChild(getFqn());
if (node == null)
{
return Collections.EMPTY_SET.iterator();
}
return new IteratorImpl(node);
}
public boolean remove(Object o)
{
o = Null.toNullObject(o);
int hashCode = o.hashCode();
int size = size();
boolean removed = false;
Object oldkey = null;
for (int i = 0; i < size; i++)
{
Object key = toLong(hashCode, i);
Object o2 = getNoUnmask(key);
if (o2 == null)
{
break;
}
if (removed)
{
// move o2 to old key
pCache_.detach(AopUtil.constructFqn(getFqn(), key));
pCache_.attach(AopUtil.constructFqn(getFqn(), oldkey), o2);
}
if (o.equals(o2))
{
pCache_.detach(AopUtil.constructFqn(getFqn(), key));
removed = true;
}
oldkey = key;
}
return removed;
}
public int size()
{
Set<Node> children = getNodeChildren();
return (children == null) ? 0 : children.size();
}
public String toString()
{
StringBuffer buf = new StringBuffer();
for (Iterator it = iterator(); it.hasNext();)
{
Object key = it.next();
buf.append("[").append(key).append("]");
if (it.hasNext()) buf.append(", ");
}
return buf.toString();
}
/**
* Return a long with "count" as the high 32 bits.
* TODO should be able to use java.lang.Long, but some CacheLoader don't
* support non-String keys
*/
private String toLong(long hashCode, long count)
{
long key = (hashCode & 0xFFFFL) | (count << 32);
return Long.toHexString(key);
}
private Object attachNoMask(Object key, Object pojo)
{
return pCache_.attach(AopUtil.constructFqn(getFqn(), key), pojo);
}
private Object getNoUnmask(Object key)
{
return pCache_.getObject(AopUtil.constructFqn(getFqn(), key));
}
public int hashCode()
{
int result = super.hashCode();
result = 29 * result + cache_.hashCode();
result = 29 * result + interceptor_.hashCode();
return result;
}
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
try
{
return super.equals(o);
}
catch (ClassCastException e)
{
return false;
}
catch (NullPointerException unused)
{
return false;
}
}
private class IteratorImpl implements Iterator
{
private Iterator<NodeSPI> iterator;
private Node node;
private Object o;
private IteratorImpl(Node node)
{
Collection<NodeSPI> children = new HashSet<NodeSPI>(((NodeSPI) node).getChildrenDirect());
iterator = children.iterator();
}
public boolean hasNext()
{
return iterator.hasNext();
}
public Object next()
{
node = iterator.next();
o = Null.toNullValue(pCache_.getObject(node.getFqn()));
return o;
}
public void remove() throws IllegalStateException
{
if (node == null)
{
throw new IllegalStateException();
}
CachedSetImpl.this.remove(o);
}
}
}
1.1 date: 2007/01/13 15:55:05; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/collection/CachedListAbstract.java
Index: CachedListAbstract.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.collection;
import org.jboss.cache.pojo.annotation.Reentrant;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* Abstract class for CachedList.
*
* @author Scott Marlow
*/
@Reentrant
abstract class CachedListAbstract implements List
{
public void clear()
{
// TODO Can use optimization here
for (int i = size() - 1; i >= 0; i--)
{
remove(i);
}
}
public boolean isEmpty()
{
return size() == 0;
}
public Object[] toArray()
{
Object[] objs = new Object[size()];
for (int i = 0; i < size(); i++)
{
objs[i] = get(i);
}
return objs;
}
public Object[] toArray(Object a[])
{
int actualLength = size();
if (actualLength > a.length) // need to allocate a larger array
a = new Object[actualLength];
int looper;
for (looper = 0; looper < actualLength; looper++)
{
a[looper] = get(looper);
}
for (; looper < a.length; looper++)
a[looper] = null; // if the array is larger than needed, set extra slots to null
return a;
}
public boolean add(Object o)
{
add(size(), o);
return true;
}
public boolean contains(Object o)
{
if (indexOf(o) != -1) return true;
return false;
}
public boolean remove(Object o)
{
int i = indexOf(o);
if (i == -1)
return false;
remove(i);
return true;
}
public boolean addAll(int index, Collection c)
{
if (c.size() == 0)
return false;
// should optimize this
for (Object o : c)
{
add(index++, o);
}
return true;
}
public boolean addAll(Collection c)
{
if (c.size() == 0)
return false;
for (Object o : c)
{
add(o);
}
return true;
}
public boolean containsAll(Collection c)
{
for (Object aC : c)
{
if (!contains(aC))
{
return false;
}
}
return true;
}
public boolean removeAll(Collection c)
{
for (Object o : c)
{
remove(o);
}
return true;
}
public int hashCode()
{
int result = 1;
for (int i = 0; i < size(); i++)
{
Object o = get(i);
result = 31 * result + (o == null ? 0 : o.hashCode());
}
return result;
}
public boolean equals(Object object)
{
if (object == this)
return true;
if (object == null || !(object instanceof List))
return false;
List list = (List) object;
if (size() != list.size())
return false;
for (int i = 0; i < list.size(); i++)
{
Object value1 = get(i);
Object value2 = list.get(i);
if ((value1 == null && value2 != null) ||
(value1 != null && !(value1.equals(value2))))
return false;
}
return true;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
int size = size();
for (int i = 0; i < size; i++)
{
Object key = get(i);
buf.append("[").append(key).append("]");
if (i <= size) buf.append(", ");
}
return buf.toString();
}
public boolean retainAll(Collection c)
{
boolean changedAnything = false;
Iterator iter = iterator();
while (iter.hasNext())
{
if (!c.contains(iter.next()))
{
iter.remove();
changedAnything = true;
}
}
return changedAnything;
}
}
1.1 date: 2007/01/13 15:55:05; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/collection/IntegerCache.java
Index: IntegerCache.java
===================================================================
package org.jboss.cache.pojo.collection;
/**
* Cache of integers in String format from 0-99.
*/
public class IntegerCache
{
private IntegerCache()
{
}
private static final String values[] = new String[100];
static
{
for (int i = 0; i < values.length; i++)
values[i] = Integer.toString(i).intern();
}
public static String toString(int i)
{
if (i >= 0 && i < values.length)
return values[i];
return Integer.toString(i);
}
}
1.1 date: 2007/01/13 15:55:05; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/collection/CachedMapImpl.java
Index: CachedMapImpl.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.collection;
import org.jboss.aop.Advised;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.pojo.PojoCacheException;
import org.jboss.cache.pojo.annotation.Reentrant;
import org.jboss.cache.pojo.impl.PojoCacheImpl;
import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
import org.jboss.cache.pojo.util.CacheApiUtil;
import org.jboss.cache.pojo.util.Null;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Map that uses cache as a backend store.
*
* @author Ben Wang
* @author Scott Marlow
*/
@Reentrant
public class CachedMapImpl implements Map
{
// protected static final Log log_ = LogFactory.getLog(CachedMapImpl.class);
private PojoCacheImpl pCache_;
private CacheSPI cache_;
private AbstractCollectionInterceptor interceptor_;
public CachedMapImpl(PojoCacheImpl pCache, AbstractCollectionInterceptor interceptor)
{
pCache_ = pCache;
cache_ = (CacheSPI) pCache_.getCache();
interceptor_ = interceptor;
}
private static Fqn constructFqn(Fqn baseFqn, Object relative)
{
if (!(relative instanceof Serializable) && !(relative instanceof Advised))
{
throw new PojoCacheException("Non-serializable for " + relative.getClass().getName());
}
return new Fqn(baseFqn, relative);
}
private Fqn getFqn()
{
return interceptor_.getFqn();
}
// implementation of the java.util.Map interface
private Set<Node> getNodeChildren()
{
return CacheApiUtil.getNodeChildren(cache_, getFqn());
}
public Object get(Object key)
{
return Null.toNullValue(pCache_.getObject(constructFqn(getFqn(), Null.toNullKeyObject(key))));
}
public Object put(Object key, Object value)
{
return pCache_.attach(constructFqn(getFqn(), Null.toNullKeyObject(key)), Null.toNullObject(value));
}
public void putAll(Map map)
{
for (Iterator i = map.entrySet().iterator(); i.hasNext();)
{
Map.Entry entry = (Map.Entry) i.next();
put(entry.getKey(), entry.getValue());
}
}
public Object remove(Object key)
{
return pCache_.detach(constructFqn(getFqn(), Null.toNullKeyObject(key)));
}
public void clear()
{
// Need to clone first to avoid CME
ArrayList list = new ArrayList(keySet());
for (int i = 0; i < list.size(); i++)
{
remove(list.get(i));
}
}
public int size()
{
Set<Node> children = getNodeChildren();
return children == null ? 0 : children.size();
}
public boolean isEmpty()
{
return size() == 0;
}
public boolean containsKey(Object object)
{
Set<Node> children = getNodeChildren();
if (children == null) return false;
for (Object n : children)
{
if (((Node) n).getFqn().getLastElement().equals(Null.toNullKeyObject(object))) return true;
}
return false;
}
public boolean containsValue(Object object)
{
return values().contains(Null.toNullObject(object));
}
public Set entrySet()
{
final CachedMapImpl map = this;
return new AbstractSet()
{
public int size()
{
Set<Node> children = getNodeChildren();
return children == null ? 0 : children.size();
}
public Iterator iterator()
{
Set<Node> children = getNodeChildren();
final Iterator i =
children == null
? Collections.EMPTY_LIST.iterator()
: children.iterator();
return new Iterator()
{
Object lastKey; // for remove
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
return new Entry(lastKey = ((Node) i.next()).getFqn().getLastElement());
}
public void remove()
{
map.remove(lastKey);
}
};
}
};
}
public Collection values()
{
final CachedMapImpl map = this;
return new AbstractCollection()
{
public int size()
{
Set<Node> children = getNodeChildren();
return children == null ? 0 : children.size();
}
public void clear()
{
map.clear();
}
public Iterator iterator()
{
Set<Node> children = getNodeChildren();
final Iterator i =
children == null
? Collections.EMPTY_LIST.iterator()
: children.iterator();
return new Iterator()
{
Object lastKey; // for remove
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
Fqn f = ((Node) i.next()).getFqn();
lastKey = f.getLastElement();
return Null.toNullValue(pCache_.getObject(f));
}
public void remove()
{
Object key = lastKey;
if (key != null) // convert from internal Null form to actual null if needed
key = Null.toNullKeyValue(key);
map.remove(key);
}
};
}
};
}
public Set keySet()
{
final CachedMapImpl map = this;
return new AbstractSet()
{
public int size()
{
Set<Node> children = getNodeChildren();
return children == null ? 0 : children.size();
}
public Iterator iterator()
{
Set<Node> children = getNodeChildren();
final Iterator i =
children == null
? Collections.EMPTY_LIST.iterator()
: children.iterator();
return new Iterator()
{
Object lastKey; // for remove
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
lastKey = ((Node) i.next()).getFqn().getLastElement();
return Null.toNullKeyValue(lastKey);
}
public void remove()
{
Object key = lastKey;
if (key != null) // convert from internal Null form to actual null if needed
key = Null.toNullKeyValue(key);
map.remove(key);
}
};
}
};
}
public int hashCode()
{
int result = 0;
for (Iterator i = entrySet().iterator(); i.hasNext();)
{
result += i.next().hashCode();
}
return result;
}
public boolean equals(Object object)
{
if (object == this)
return true;
if (object == null || !(object instanceof Map))
return false;
Map map = (Map) object;
if (size() != map.size())
return false;
for (Iterator i = entrySet().iterator(); i.hasNext();)
{
Entry entry = (Entry) i.next();
Object value = entry.getValue();
Object key = entry.getKey();
if (value == null)
{
if (!(map.get(key) == null && map.containsKey(key)))
{
return false;
}
} else
{
if (!value.equals(map.get(key)))
return false;
}
}
return true;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
Set set = keySet();
for (Iterator it = set.iterator(); it.hasNext();)
{
Object key = it.next();
buf.append("[").append(key).append(", ").append(get(key)).append("]");
if (it.hasNext()) buf.append(", ");
}
return buf.toString();
}
class Entry implements Map.Entry
{
Object key;
public Entry(Object key)
{
this.key = key;
}
public Object getKey()
{
return Null.toNullValue(key);
}
public Object getValue()
{
return Null.toNullValue(pCache_.getObject(constructFqn(getFqn(), key)));
}
public Object setValue(Object value)
{
return pCache_.attach(constructFqn(getFqn(), key), Null.toNullObject(value));
}
public int hashCode()
{
Object value = getValue();
return ((key == null) ? 0 : key.hashCode())
^ ((value == null) ? 0 : value.hashCode());
}
public boolean equals(Object obj)
{
if (!(obj instanceof Entry))
return false;
Entry entry = (Entry) obj;
Object value = getValue();
return (
key == null
? entry.getKey() == null
: key.equals(entry.getKey()))
&& (value == null
? entry.getValue() == null
: value.equals(entry.getValue()));
}
}
}
More information about the jboss-cvs-commits
mailing list