Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 276   Methods: 7
NCLOC: 214   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CollectionClassHandler.java 67.4% 84.9% 100% 80.1%
coverage coverage
 1    /*
 2    * JBoss, Home of Professional Open Source
 3    *
 4    * Distributable under LGPL license.
 5    * See terms of license at gnu.org.
 6    */
 7   
 8    package org.jboss.cache.pojo.impl;
 9   
 10    import org.apache.commons.logging.Log;
 11    import org.apache.commons.logging.LogFactory;
 12    import org.jboss.aop.advice.Interceptor;
 13    import org.jboss.aop.proxy.ClassProxy;
 14    import org.jboss.cache.Cache;
 15    import org.jboss.cache.CacheException;
 16    import org.jboss.cache.CacheSPI;
 17    import org.jboss.cache.Fqn;
 18    import org.jboss.cache.pojo.PojoCacheException;
 19    import org.jboss.cache.pojo.collection.CollectionInterceptorUtil;
 20    import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
 21    import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor;
 22   
 23    import java.util.Iterator;
 24    import java.util.List;
 25    import java.util.Map;
 26    import java.util.Set;
 27   
 28    /**
 29    * Handling the Collection class management. Has no consideration of object graph here.
 30    *
 31    * @author Ben Wang
 32    * Date: Aug 4, 2005
 33    * @version $Id: CollectionClassHandler.java,v 1.4 2007/06/28 00:56:06 jgreene Exp $
 34    */
 35    class CollectionClassHandler
 36    {
 37    private final Log log = LogFactory.getLog(CollectionClassHandler.class);
 38    private Cache<Object, Object> cache_;
 39    private PojoCacheImpl pCache_;
 40    private InternalHelper internal_;
 41   
 42  499 public CollectionClassHandler(PojoCacheImpl pCache, InternalHelper internal)
 43    {
 44  499 pCache_ = pCache;
 45  499 cache_ = pCache_.getCache();
 46  499 internal_ = internal;
 47    }
 48   
 49  75 Object get(Fqn fqn, Class clazz, PojoInstance pojoInstance)
 50    throws CacheException
 51    {
 52  75 Object obj = null;
 53  75 try
 54    {
 55  75 if (Map.class.isAssignableFrom(clazz))
 56    {
 57  6 Object map = clazz.newInstance();
 58  6 obj = CollectionInterceptorUtil.createMapProxy(pCache_, fqn, clazz, (Map) map);
 59    }
 60  69 else if (List.class.isAssignableFrom(clazz))
 61    {
 62  64 Object list = clazz.newInstance();
 63  64 obj = CollectionInterceptorUtil.createListProxy(pCache_, fqn, clazz, (List) list);
 64    }
 65  5 else if (Set.class.isAssignableFrom(clazz))
 66    {
 67  5 Object set = clazz.newInstance();
 68  5 obj = CollectionInterceptorUtil.createSetProxy(pCache_, fqn, clazz, (Set) set);
 69    }
 70    }
 71    catch (Exception e)
 72    {
 73  0 throw new CacheException("failure creating proxy", e);
 74    }
 75   
 76  75 return obj;
 77    }
 78   
 79  1673 void put(Fqn fqn, Fqn referencingFqn, Object obj) throws CacheException
 80    {
 81  1673 boolean isCollection = false;
 82   
 83  1673 CachedType type = null;
 84  1673 if (obj instanceof ClassProxy)
 85    {
 86  0 throw new IllegalStateException("CollectionClassHandler.put(): obj is an ClassProxy instance " + obj);
 87    }
 88   
 89  1673 type = pCache_.getCachedType(obj.getClass());
 90   
 91    //JBCACHE-760: for collection - put initialized aopInstance in fqn
 92  1673 if (!(obj instanceof Map || obj instanceof List || obj instanceof Set))
 93    {
 94  0 return;
 95    }
 96   
 97    // Always initialize the ref count so that we can mark this as an AopNode.
 98  1673 PojoInstance pojoInstance = InternalHelper.initializeAopInstance(referencingFqn);
 99  1673 pojoInstance.set(obj);
 100  1673 pojoInstance.setPojoClass(type.getType());
 101  1673 cache_.put(fqn, PojoInstance.KEY, pojoInstance);
 102   
 103  1673 if (obj instanceof Map)
 104    {
 105  104 if (log.isDebugEnabled())
 106    {
 107  0 log.debug("collectionPutObject(): aspectized obj is a Map type of size: " + ((Map) obj).size());
 108    }
 109   
 110    // Let's replace it with a proxy if necessary
 111  104 Map map = (Map) obj;
 112  104 if (!(obj instanceof ClassProxy))
 113    {
 114  104 Class clazz = obj.getClass();
 115  104 try
 116    {
 117  104 obj = CollectionInterceptorUtil.createMapProxy(pCache_, fqn, clazz, (Map) obj);
 118    }
 119    catch (Exception e)
 120    {
 121  0 throw new CacheException("failure creating proxy", e);
 122    }
 123   
 124  104 checkMapRecursion(map, obj);
 125    }
 126   
 127  104 isCollection = true;
 128    // populate via the proxied collection
 129  104 for (Iterator i = map.entrySet().iterator(); i.hasNext();)
 130    {
 131  204 Map.Entry entry = (Map.Entry) i.next();
 132  204 ((Map) obj).put(entry.getKey(), entry.getValue());
 133    }
 134   
 135    }
 136  1569 else if (obj instanceof List)
 137    {
 138  1508 if (log.isDebugEnabled())
 139    {
 140  0 log.debug("collectionPutObject(): aspectized obj is a List type of size: "
 141    + ((List) obj).size());
 142    }
 143   
 144  1508 List list = (List) obj;
 145   
 146    // Let's replace it with a proxy if necessary
 147  1508 if (!(obj instanceof ClassProxy))
 148    {
 149  1508 Class clazz = obj.getClass();
 150  1508 try
 151    {
 152  1508 obj = CollectionInterceptorUtil.createListProxy(pCache_, fqn, clazz, (List) obj);
 153    }
 154    catch (Exception e)
 155    {
 156  0 throw new CacheException("failure creating proxy", e);
 157    }
 158   
 159  1508 checkListRecursion(list, obj);
 160    }
 161   
 162  1508 isCollection = true;
 163    // populate via the proxied collection
 164  1508 for (Iterator i = list.iterator(); i.hasNext();)
 165    {
 166  3134 ((List) obj).add(i.next());
 167    }
 168   
 169    }
 170  61 else if (obj instanceof Set)
 171    {
 172  61 if (log.isDebugEnabled())
 173    {
 174  0 log.debug("collectionPutObject(): aspectized obj is a Set type of size: "
 175    + ((Set) obj).size());
 176    }
 177   
 178  61 Set set = (Set) obj;
 179   
 180    // Let's replace it with a proxy if necessary
 181  61 if (!(obj instanceof ClassProxy))
 182    {
 183  61 Class clazz = obj.getClass();
 184  61 try
 185    {
 186  61 obj = CollectionInterceptorUtil.createSetProxy(pCache_, fqn, clazz, (Set) obj);
 187    }
 188    catch (Exception e)
 189    {
 190  0 throw new CacheException("failure creating proxy", e);
 191    }
 192   
 193  61 checkSetRecursion(set, obj);
 194    }
 195   
 196  61 isCollection = true;
 197    // populate via the proxied collection
 198  61 for (Iterator i = set.iterator(); i.hasNext();)
 199    {
 200  120 ((Set) obj).add(i.next());
 201    }
 202   
 203    }
 204   
 205  1672 if (isCollection)
 206    {
 207    // Need to reset it here in case this is a new proxy instance
 208  1672 pojoInstance.set(obj);
 209    // Attach pojoReference to that interceptor
 210  1672 BaseInterceptor baseInterceptor = (BaseInterceptor) CollectionInterceptorUtil.getInterceptor(
 211    (ClassProxy) obj);
 212  1672 baseInterceptor.setAopInstance(pojoInstance);
 213    }
 214    }
 215   
 216  1508 private void checkListRecursion(List list, Object obj)
 217    {
 218  1508 while (true)
 219    {
 220  1509 int i = list.indexOf(list); // check for recursion
 221  1508 if (i == -1) break;
 222   
 223  1 list.remove(list);
 224  1 list.add(i, obj);
 225    }
 226    }
 227   
 228  61 private void checkSetRecursion(Set set, Object obj)
 229    {
 230  61 if (set.remove(set))
 231    {
 232  0 set.add(obj); // replace with proxy
 233  0 throw new PojoCacheException("CollectionClassHandler.checkSetRecursion(): " +
 234    "detect a recursive set (e.g., set inside the same set). This will fail to " +
 235    "replicate even outside of PojoCache with HashSet. " + set);
 236    }
 237    }
 238   
 239  104 private void checkMapRecursion(Map map, Object obj)
 240    {
 241  104 Map m = java.util.Collections.unmodifiableMap(map);
 242   
 243  104 for (Object k : m.keySet())
 244    {
 245  204 if (m == k)
 246    {
 247  0 throw new PojoCacheException("CollectionClassHandler.checkMapRecursion(): " +
 248    " Can't handle the recursion map where it is nested in a constant key " + map);
 249    }
 250   
 251  204 Object v = m.get(k);
 252  204 if (v == map)
 253    {
 254  0 throw new PojoCacheException("CollectionClassHandler.checkMapRecursion(): " +
 255    "detect a recursive map (e.g., map inside the same map). This will fail to " +
 256    "replicate even outside of PojoCache with HashMap because of hashCode. " + map);
 257    // recursion here, replace it with proxy
 258    // map.put(k, obj);
 259    }
 260    }
 261    }
 262   
 263  1332 Object remove(Fqn fqn, Object obj) throws CacheException
 264    {
 265  1332 if (!(obj instanceof ClassProxy))
 266    {
 267  0 throw new PojoCacheException("CollectionClassHandler.collectionRemoveObject(): object is not a proxy :" + obj);
 268    }
 269   
 270  1332 Interceptor interceptor = CollectionInterceptorUtil.getInterceptor((ClassProxy) obj);
 271  1332 boolean removeFromCache = true;
 272    // detach the interceptor. This will trigger a copy and remove.
 273  1332 ((AbstractCollectionInterceptor) interceptor).detach(removeFromCache);
 274  1332 return ((AbstractCollectionInterceptor) interceptor).getCurrentCopy();
 275    }
 276    }