[jboss-cvs] JBossCache/old/src/org/jboss/cache/aop/collection ...
Ben Wang
bwang at jboss.com
Tue Oct 31 03:01:15 EST 2006
User: bwang
Date: 06/10/31 03:01:15
Added: old/src/org/jboss/cache/aop/collection
AbstractCollectionInterceptor.java
CachedMapImpl.java CachedSetImpl.java
CachedSetInterceptor.java
CachedListInterceptor.java CachedListImpl.java
CachedMapInterceptor.java CachedListAbstract.java
CollectionInterceptorUtil.java
Log:
Deprecated files moved to old dir.
Revision Changes Path
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/collection/AbstractCollectionInterceptor.java
Index: AbstractCollectionInterceptor.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.aop.collection;
import org.jboss.cache.Fqn;
import org.jboss.cache.aop.BaseInterceptor;
import org.jboss.cache.aop.AOPInstance;
/**
* Abstract base class for collection interceptor.
*
* @author Ben Wang
* @version $Id: AbstractCollectionInterceptor.java,v 1.1 2006/10/31 08:01:15 bwang Exp $
*/
public abstract class AbstractCollectionInterceptor implements BaseInterceptor {
protected Fqn fqn_;
protected boolean attached_ = true;
protected AOPInstance aopInstance_;
public Fqn getFqn()
{
return fqn_;
}
public void setFqn(Fqn fqn)
{
this.fqn_ = fqn;
}
public AOPInstance getAopInstance() {
return aopInstance_;
}
public void setAopInstance(AOPInstance aopInstance) {
this.aopInstance_ = aopInstance;
}
public void attach(Fqn fqn, boolean copyToCache)
{
// This is a hook to allow re-attching the Collection without specifying the fqn.
if(fqn != null)
{
setFqn(fqn);
}
attached_ = true;
// Reattach anything in-memory to cache
}
public void detach(boolean removeFromCache)
{
attached_ = false;
// Detach by tranferring the cache content to in-memory copy
}
public boolean isAttached()
{
return attached_;
}
}
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/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.aop.collection;
import org.jboss.cache.CacheException;
import org.jboss.cache.Fqn;
import org.jboss.cache.DataNode;
import org.jboss.cache.aop.PojoCache;
import org.jboss.cache.aop.util.AopUtil;
import org.jboss.cache.aop.util.Null;
import java.util.*;
/**
* Map that uses cache as a backend store.
*
* @author Ben Wang
* @author Scott Marlow
*/
public class CachedMapImpl implements Map
{
// protected static final Log log_ = LogFactory.getLog(CachedMapImpl.class);
protected PojoCache cache_;
protected AbstractCollectionInterceptor interceptor_;
protected CachedMapImpl(PojoCache cache, AbstractCollectionInterceptor interceptor)
{
this.cache_ = cache;
interceptor_ = interceptor;
}
protected Fqn getFqn()
{
return interceptor_.getFqn();
}
// implementation of the java.util.Map interface
protected DataNode getNode()
{
try {
return cache_._get(getFqn());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object get(Object key)
{
try {
return Null.toNullValue(cache_.getObject(AopUtil.constructFqn(getFqn(), Null.toNullKeyObject(key))));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object put(Object key, Object value)
{
try {
return cache_.putObject(AopUtil.constructFqn(getFqn(), Null.toNullKeyObject(key)), Null.toNullObject(value));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
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)
{
try {
return cache_.removeObject(AopUtil.constructFqn(getFqn(), Null.toNullKeyObject(key)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
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()
{
DataNode node = getNode();
if(node == null) {
return 0;
}
Map children = node.getChildren();
return children == null ? 0 : children.size();
}
public boolean isEmpty()
{
return size() == 0;
}
public boolean containsKey(Object object)
{
Map children = getNode().getChildren();
if(object != null) // if not null,
object = object.toString(); // convert to internal form which is always string
return children != null && children.containsKey(Null.toNullKeyObject(object));
}
public boolean containsValue(Object object)
{
return values().contains(Null.toNullObject(object));
}
public Set entrySet()
{
final CachedMapImpl map = this;
return new AbstractSet()
{
public int size()
{
Map children = getNode().getChildren();
return children == null ? 0 : children.size();
}
public Iterator iterator()
{
Map children = getNode().getChildren();
final Iterator i =
children == null
? Collections.EMPTY_LIST.iterator()
: children.keySet().iterator();
return new Iterator()
{
Object lastKey; // for remove
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
return new Entry(lastKey = i.next());
}
public void remove()
{
map.remove(lastKey);
}
};
}
};
}
public Collection values()
{
final CachedMapImpl map = this;
return new AbstractCollection()
{
public int size()
{
Map children = getNode().getChildren();
return children == null ? 0 : children.size();
}
public void clear() {
map.clear();
}
public Iterator iterator()
{
Map children = getNode().getChildren();
final Iterator i =
children == null
? Collections.EMPTY_LIST.iterator()
: children.keySet().iterator();
return new Iterator()
{
Object lastKey; // for remove
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
try
{
lastKey = i.next();
return Null.toNullValue(cache_.getObject(AopUtil.constructFqn(getFqn(), lastKey)));
}
catch (CacheException e)
{
throw new RuntimeException(e);
}
}
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()
{
Map children = getNode().getChildren();
return children == null ? 0 : children.size();
}
public Iterator iterator()
{
Map children = getNode().getChildren();
final Iterator i =
children == null
? Collections.EMPTY_LIST.iterator()
: children.keySet().iterator();
return new Iterator()
{
Object lastKey; // for remove
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
lastKey = i.next();
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 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 (map.get(key) == null
|| !map.containsKey(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();
}
protected class Entry implements Map.Entry
{
Object key;
public Entry(Object key)
{
this.key = key;
}
public Object getKey()
{
return Null.toNullValue(key);
}
public Object getValue()
{
try {
return Null.toNullValue(cache_.getObject(AopUtil.constructFqn(getFqn(), key)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object setValue(Object value)
{
try {
return cache_.putObject(AopUtil.constructFqn(getFqn(), key), Null.toNullObject(value));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
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()));
}
}
}
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/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.aop.collection;
import org.jboss.cache.CacheException;
import org.jboss.cache.DataNode;
import org.jboss.cache.Fqn;
import org.jboss.cache.aop.PojoCache;
import org.jboss.cache.aop.util.AopUtil;
import org.jboss.cache.aop.util.Null;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Set that uses cache as a underlying backend store
*
* @author Ben Wang
* @author Scott Marlow
* @author Jussi Pyorre
*/
public class CachedSetImpl extends AbstractSet
{
// protected static final Log log_=LogFactory.getLog(CachedSetImpl.class);
protected PojoCache cache_;
protected AbstractCollectionInterceptor interceptor_;
public CachedSetImpl(PojoCache cache, AbstractCollectionInterceptor interceptor)
{
this.cache_ = cache;
this.interceptor_ = interceptor;
}
protected DataNode getNode()
{
try
{
return cache_._get(getFqn());
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
protected Fqn getFqn()
{
// Need this since fqn can be reset.
return interceptor_.getFqn();
}
// implementation of the java.util.Set interface
public int size()
{
return keySet().size();
}
public Iterator iterator()
{
return new IteratorImpl(keySet());
}
public boolean add(Object o)
{
Collection keys = keySet();
// This could be done with 'contains(o)' but it would invoke 'keySet()'
// twice
for (Iterator iter = new IteratorImpl(keys); iter.hasNext();)
if (iter.next() == o)
return false;
// Search for an available key. This is a fast operation as the key set
// is already available. Start with the size of the key set and go
// up as this will be the fastest way to find an unused key. Gaps
// in the keys don't matter, as this is a Set not a List
int key = keys.size();
String keyString;
while (keys.contains((keyString = Integer.toString(key))))
key++;
try
{
cache_.putObject(AopUtil.constructFqn(getFqn(), keyString), Null.toNullObject(o));
return true;
}
catch (CacheException e)
{
throw new RuntimeException(e);
}
}
public boolean contains(Object o)
{
Iterator iter = iterator();
if (o == null)
{
while (iter.hasNext())
{
if (iter.next() == null)
{
return true;
}
}
}
else
{
while (iter.hasNext())
{
if (o.equals(iter.next()))
{
return true;
}
}
}
return false;
}
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();
}
public boolean equals(Object o)
{
if (o == null)
return false;
if (o == this)
return true;
try
{
Set set = (Set) o;
return (set.size() == keySet().size() && this.containsAll(set));
}
catch (ClassCastException e)
{
return false;
}
catch (NullPointerException unused)
{
return false;
}
}
private Collection keySet()
{
DataNode node = getNode();
if (node != null)
{
Map children = node.getChildren();
if (children != null)
{
return children.keySet();
}
}
return Collections.EMPTY_SET;
}
private class IteratorImpl implements Iterator
{
private Iterator iterator;
private Object key;
private IteratorImpl(Collection keys)
{
iterator = keys.iterator();
}
public boolean hasNext()
{
return iterator.hasNext();
}
public Object next()
{
// (Brian) Removed Jussi's call to iterator.hasNext() followed by
// an NSOE if false. That approach was slightly more efficient if
// hasNext() were false, but in the vast majority of cases iterators
// are used correctly and it was an extra step.
this.key = iterator.next();
try
{
return Null.toNullValue(cache_.getObject(AopUtil.constructFqn(getFqn(), this.key)));
}
catch (CacheException e)
{
throw new RuntimeException(e);
}
}
public void remove() throws IllegalStateException
{
if (this.key == null)
{
throw new IllegalStateException();
}
try
{
cache_.removeObject(AopUtil.constructFqn(getFqn(), this.key));
}
catch (CacheException e)
{
throw new RuntimeException(e);
}
}
}
}
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/collection/CachedSetInterceptor.java
Index: CachedSetInterceptor.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.aop.collection;
import org.jboss.cache.Fqn;
import org.jboss.cache.aop.PojoCache;
import java.util.*;
/**
* Set interceptor that delegates underlying impl.
*
* @author Ben Wang
*/
public class CachedSetInterceptor extends AbstractCollectionInterceptor
{
// protected static final Log log_=LogFactory.getLog(CachedSetInterceptor.class);
protected Map methodMap_;
protected static final Map managedMethods_ =
CollectionInterceptorUtil.getManagedMethods(Set.class);
protected Set cacheImpl_;
protected Set current_;
protected Set inMemImpl_;
public CachedSetInterceptor(PojoCache cache, Fqn fqn, Class clazz, Set obj)
{
this.fqn_ = fqn;
methodMap_ = CollectionInterceptorUtil.getMethodMap(clazz);
cacheImpl_ = new CachedSetImpl(cache, this);
inMemImpl_ = obj;
current_ = cacheImpl_;
}
/**
* When we want to associate this proxy with the cache again. We will need to translate the in-memory
* content to the cache store first.
*/
public void attach(Fqn fqn, boolean copyToCache)
{
super.attach(fqn, copyToCache);
if(copyToCache)
toCache();
current_ = cacheImpl_;
}
protected void toCache()
{
if(inMemImpl_ == null)
throw new IllegalStateException("CachedSetInterceptor.toCache(). inMemImpl is null.");
for(Iterator it = inMemImpl_.iterator(); it.hasNext();)
{
Object obj = it.next();
it.remove();
cacheImpl_.add(obj);
}
inMemImpl_ = null; // we are done with this.
}
/**
* When we want to separate this proxy from the cache. We will destroy the cache content and copy them to
* the in-memory copy.
*/
public void detach(boolean removeFromCache)
{
super.detach(removeFromCache);
toMemory(removeFromCache);
current_ = inMemImpl_;
}
protected void toMemory(boolean removeFromCache)
{
if(inMemImpl_ == null)
{
inMemImpl_ = new HashSet();
}
// TODO. This needs optimization.
inMemImpl_.clear();
for(Iterator it = cacheImpl_.iterator(); it.hasNext();)
{
Object obj = it.next();
if(removeFromCache)
it.remove();
inMemImpl_.add(obj);
}
}
public String getName()
{
return "CachedSetInterceptor";
}
public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable
{
if( current_ == null)
throw new IllegalStateException("CachedSetInterceptor.invoke(). current_ is null.");
return CollectionInterceptorUtil.invoke(invocation,
current_,
methodMap_,
managedMethods_);
}
}
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/collection/CachedListInterceptor.java
Index: CachedListInterceptor.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.aop.collection;
import org.jboss.cache.Fqn;
import org.jboss.cache.aop.PojoCache;
import java.util.*;
/**
* List ineterceptor that delegates to underlying implementation.
*
* @author Ben Wang
*/
public class CachedListInterceptor extends AbstractCollectionInterceptor
{
// protected static final Log log_ = LogFactory.getLog(CachedListInterceptor.class);
protected static final Map managedMethods_ =
CollectionInterceptorUtil.getManagedMethods(List.class);
protected Map methodMap_;
// This is the copy in cache store when it is attached.
protected List cacheImpl_;
// This is the copy in-memory when the state is detached.
protected List inMemImpl_;
// Whichever is used now.
protected List current_;
public CachedListInterceptor(PojoCache cache, Fqn fqn, Class clazz, List obj)
{
this.fqn_ = fqn;
methodMap_ = CollectionInterceptorUtil.getMethodMap(clazz);
cacheImpl_ = new CachedListImpl(cache, this);
inMemImpl_ = obj; // lazy initialization here.
current_ = cacheImpl_;
}
/**
* When we want to associate this proxy with the cache again. We will need to translate the in-memory
* content to the cache store first.
*/
public void attach(Fqn fqn, boolean copyToCache)
{
super.attach(fqn, copyToCache);
if(copyToCache)
toCache();
current_ = cacheImpl_;
}
protected void toCache()
{
if(inMemImpl_ == null)
throw new IllegalStateException("CachedListInterceptor.toCache(). inMemImpl is null.");
// TODO This may not be optimal
List tmpList = new ArrayList();
for(int i = inMemImpl_.size(); i > 0; i--)
{
Object obj = inMemImpl_.remove(i-1);
tmpList.add(obj);
}
int size = tmpList.size();
for(int i=0; i < tmpList.size(); i++)
{
cacheImpl_.add(tmpList.get(size-i-1));
}
inMemImpl_ = null; // we are done with this.
}
/**
* When we want to separate this proxy from the cache. We will destroy the cache content and copy them to
* the in-memory copy.
*/
public void detach(boolean removeFromCache)
{
super.detach(removeFromCache);
toMemory(removeFromCache);
current_ = inMemImpl_;
}
protected void toMemory(boolean removeFromCache)
{
if(inMemImpl_ == null)
{
inMemImpl_ = new ArrayList();
}
// Optimization since remove from the beginning is very expensive.
List tmpList = new ArrayList();
for(int i = cacheImpl_.size(); i > 0; i--)
{
int j = i-1;
Object obj = null;
if(removeFromCache)
{
obj = cacheImpl_.remove(j);
} else
{
obj = cacheImpl_.get(j);
}
tmpList.add(obj);
}
int size = tmpList.size();
inMemImpl_.clear();
for(int i=0; i < tmpList.size(); i++)
{
inMemImpl_.add(tmpList.get(size-i-1));
}
}
public String getName()
{
return "CachedListInterceptor";
}
public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable
{
if( current_ == null)
throw new IllegalStateException("CachedListInterceptor.invoke(). current_ is null.");
return CollectionInterceptorUtil.invoke(invocation,
current_,
methodMap_,
managedMethods_);
}
}
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/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.aop.collection;
import org.jboss.cache.Fqn;
import org.jboss.cache.DataNode;
import org.jboss.cache.aop.PojoCache;
import org.jboss.cache.aop.util.AopUtil;
import org.jboss.cache.aop.util.Null;
import java.util.*;
/**
* List implementation that uses cache as a backend store.
*
* @author Ben Wang
* @author Scott Marlow
*/
public class CachedListImpl extends CachedListAbstract implements List
{
// protected static final Log log_ = LogFactory.getLog(CachedListImpl.class);
protected PojoCache cache_;
protected AbstractCollectionInterceptor interceptor_;
public CachedListImpl(PojoCache cache, AbstractCollectionInterceptor interceptor)
{
cache_ = cache;
interceptor_ = interceptor;
}
protected Fqn getFqn()
{
return interceptor_.getFqn();
}
// implementation of the java.util.List interface
protected DataNode getNode()
{
try {
return cache_._get(getFqn());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object get(int index)
{
checkIndex(index);
try {
return Null.toNullValue(cache_.getObject(AopUtil.constructFqn(getFqn(), Integer.toString(index))));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void checkIndex(int i) {
// 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()
{
DataNode node = getNode();
if(node == null) {
return 0;
}
Map children = node.getChildren();
return children == null ? 0 : children.size();
}
public Object set(int index, Object element)
{
try {
if(index != 0)
checkIndex(index-1); // Since index can be size().
return Null.toNullValue(cache_.putObject(AopUtil.constructFqn(getFqn(), Integer.toString(index)), Null.toNullObject(element)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void add(int index, Object element)
{
try {
if(index != 0)
checkIndex(index-1); // Since index can be size().
for (int i = size(); i > index; i--) {
Object obj = cache_.removeObject(AopUtil.constructFqn(getFqn(), Integer.toString(i - 1)));
cache_.putObject(AopUtil.constructFqn(getFqn(), Integer.toString(i)), obj);
}
cache_.putObject(AopUtil.constructFqn(getFqn(), Integer.toString(index)), Null.toNullObject(element));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
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)
{
try {
checkIndex(index);
// Object result = cache.removeObject(((Fqn) fqn.clone()).add(new Integer(index)));
int size = size();
Object result = Null.toNullValue(cache_.removeObject(AopUtil.constructFqn(getFqn(), Integer.toString(index))));
if( size == (index +1)) {
return result; // We are the last one.
}
for (int i = index; i < size-1; i++) {
Object obj = cache_.removeObject(AopUtil.constructFqn(getFqn(), Integer.toString(i + 1)));
cache_.putObject(AopUtil.constructFqn(getFqn(), Integer.toString(i)), obj);
}
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Iterator iterator()
{
// TODO: check for concurrent modification
return new Iterator()
{
// Need to share this
protected int current = -1;
protected 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());
try {
return Null.toNullValue(cache_.getObject(AopUtil.constructFqn(getFqn(), Integer.toString(++current))));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void remove()
{
// TODO Need optimization here since set does not care about index
try {
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 = cache_.removeObject(AopUtil.constructFqn(getFqn(), Integer.toString(current)));
for(int i = current+1 ; i < size; i++) {
last = cache_.removeObject(AopUtil.constructFqn(getFqn(), Integer.toString(i)));
cache_.putObject(AopUtil.constructFqn(getFqn(), Integer.toString(i-1)), last);
}
} else { // we are the last index.
// Need to move back the cursor.
cache_.removeObject(AopUtil.constructFqn(getFqn(), Integer.toString(current)));
}
current--;
size--;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
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);
}
protected static class MyListIterator implements ListIterator {
protected int index = 0;
protected 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()
{
try {
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--;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean hasNext()
{
return (index != list_.size() - 1);
}
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()
{
protected int current = -1;
protected 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++;
try {
return iter_.next();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
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: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/collection/CachedMapInterceptor.java
Index: CachedMapInterceptor.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.aop.collection;
import org.jboss.cache.Fqn;
import org.jboss.cache.aop.PojoCache;
import java.util.*;
/**
* Map interceptor that delegates to the underlying impl.
*
* @author Ben Wang
*/
public class CachedMapInterceptor extends AbstractCollectionInterceptor
{
// protected static final Log log_ = LogFactory.getLog(CachedMapInterceptor.class);
protected static final Map managedMethods_ =
CollectionInterceptorUtil.getManagedMethods(Map.class);
protected Map methodMap_;
protected Map cacheImpl_;
protected Map inMemImpl_;
protected Map current_;
protected CachedMapInterceptor(PojoCache cache, Fqn fqn, Class clazz, Map obj)
{
this.fqn_ = fqn;
methodMap_ = CollectionInterceptorUtil.getMethodMap(clazz);
cacheImpl_ = new CachedMapImpl(cache, this);
inMemImpl_ = obj;
current_ = cacheImpl_;
}
/**
* When we want to associate this proxy with the cache again. We will need to translate the in-memory
* content to the cache store first.
*/
public void attach(Fqn fqn, boolean copyToCache)
{
super.attach(fqn, copyToCache);
if(copyToCache)
toCache();
current_ = cacheImpl_;
}
protected void toCache()
{
if(inMemImpl_ == null)
throw new IllegalStateException("CachedMapInterceptor.toCache(). inMemImpl is null.");
Iterator it = inMemImpl_.keySet().iterator();
while(it.hasNext())
{
Object key = it.next();
Object val = inMemImpl_.get(key);
cacheImpl_.put(key, val);
}
inMemImpl_.clear();
inMemImpl_ = null; // we are done with this.
}
/**
* When we want to separate this proxy from the cache. We will destroy the cache content and copy them to
* the in-memory copy.
*/
public void detach(boolean removeFromCache)
{
super.detach(removeFromCache);
toMemory(removeFromCache);
current_ = inMemImpl_;
}
protected void toMemory(boolean removeFromCache)
{
if(inMemImpl_ == null)
{
inMemImpl_ = new HashMap();
}
Iterator it = cacheImpl_.keySet().iterator();
inMemImpl_.clear();
while(it.hasNext())
{
Object key = it.next();
Object val = null;
if(removeFromCache)
{
val = cacheImpl_.remove(key);
} else
{
val = cacheImpl_.get(key);
}
inMemImpl_.put(key, val);
}
}
public String getName()
{
return "CachedMapInterceptor";
}
public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable
{
if( current_ == null)
throw new IllegalStateException("CachedMapInterceptor.invoke(). current_ is null.");
return CollectionInterceptorUtil.invoke(invocation,
current_,
methodMap_,
managedMethods_);
}
}
1.1 date: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/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.aop.collection;
import java.util.List;
import java.util.Collection;
import java.util.Iterator;
/**
* Abstract class for CachedList
*
* @author Scott Marlow
*/
public 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;
Iterator i = c.iterator();
// should optimize this
while(i.hasNext()) {
Object o = i.next();
add(index++,o);
}
return true;
}
public boolean addAll(Collection c)
{
if(c.size() == 0)
return false;
Iterator i = c.iterator();
while(i.hasNext()) {
Object o = i.next();
add(o);
}
return true;
}
public boolean containsAll(Collection c)
{
Iterator iter = c.iterator();
while (iter.hasNext()) {
if(!contains(iter.next())) {
return false;
}
}
return true;
}
public boolean removeAll(Collection c)
{
Iterator i = c.iterator();
while(i.hasNext()) {
Object o = i.next();
remove(o);
}
return true;
}
public int hashCode()
{
int result = 0;
for (int i =0; i < size(); i++) {
Object o = get(i);
result += (o == null ? 0 : o.hashCode());
}
return result;
}
public boolean equals(Object object)
{
if (object == this)
return true;
if (!(object instanceof List))
return false;
List list = (List) object;
if (size() != list.size())
return false;
for (int i=0; i < list.size(); i++) {
Object value = list.get(i);
if( !contains(value) )
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: 2006/10/31 08:01:15; author: bwang; state: Exp;JBossCache/old/src/org/jboss/cache/aop/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.aop.collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.aop.InstanceAdvisor;
import org.jboss.aop.advice.Interceptor;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;
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.aop.PojoCache;
import org.jboss.cache.aop.util.AopUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
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
{
static Log log=LogFactory.getLog(CollectionInterceptorUtil.class.getName());
public static ClassProxy createProxy(Class clazz, AbstractCollectionInterceptor interceptor)
throws Exception
{
ClassProxy result = ClassProxyFactory.newInstance(clazz);
InstanceAdvisor advisor = result._getInstanceAdvisor();
advisor.appendInterceptor(interceptor);
return result;
}
public static ClassProxy createMapProxy(PojoCache cache, Fqn fqn, Class clazz, Map obj) throws Exception {
return CollectionInterceptorUtil.createProxy(clazz, new CachedMapInterceptor(cache, fqn, clazz, obj));
}
public static ClassProxy createListProxy(PojoCache cache, Fqn fqn, Class clazz, List obj) throws Exception {
return CollectionInterceptorUtil.createProxy(clazz, new CachedListInterceptor(cache, fqn, clazz, obj));
}
public static ClassProxy createSetProxy(PojoCache 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 RuntimeException(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 RuntimeException("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(new Long(hash), methods[i]);
}
// Add toString to ManagedMethod
long hash = MethodHashing.methodHash(tostring);
managedMethods.put(new Long(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 = new Long(methodInvocation.getMethodHash());
Method method = (Method) managedMethods.get(methodHash);
if (log.isDebugEnabled() && 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);
}
log.trace("invke(): invoke non-managed method: " +method.toString());
Object target = methodInvocation.getTargetObject();
if(target == null) {
throw new RuntimeException("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();
}
}
More information about the jboss-cvs-commits
mailing list