[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