Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 253   Methods: 6
NCLOC: 187   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AdvisedPojoHandler.java 76.5% 88.4% 100% 85.7%
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 java.lang.reflect.Field;
 11    import java.util.HashMap;
 12    import java.util.Iterator;
 13    import java.util.List;
 14    import java.util.Map;
 15    import java.util.Set;
 16   
 17    import org.apache.commons.logging.Log;
 18    import org.apache.commons.logging.LogFactory;
 19    import org.jboss.aop.Advised;
 20    import org.jboss.aop.Advisor;
 21    import org.jboss.aop.ClassInstanceAdvisor;
 22    import org.jboss.aop.InstanceAdvisor;
 23    import org.jboss.cache.Cache;
 24    import org.jboss.cache.CacheException;
 25    import org.jboss.cache.Fqn;
 26    import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
 27    import org.jboss.cache.pojo.memory.FieldPersistentReference;
 28    import org.jboss.cache.pojo.util.AopUtil;
 29   
 30    /**
 31    * Handling the advised pojo operations. No consideration of object graph here.
 32    *
 33    * @author Ben Wang
 34    * Date: Aug 4, 2005
 35    * @version $Id: AdvisedPojoHandler.java,v 1.8 2007/06/21 17:43:58 jgreene Exp $
 36    */
 37    class AdvisedPojoHandler
 38    {
 39    private final Log log = LogFactory.getLog(AdvisedPojoHandler.class);
 40    private Cache<Object, Object> cache_;
 41    private PojoCacheImpl pCache_;
 42    private PojoUtil util_;
 43   
 44  499 public AdvisedPojoHandler(PojoCacheImpl pCache, InternalHelper internal,
 45    PojoUtil util)
 46    {
 47  499 pCache_ = pCache;
 48  499 cache_ = pCache_.getCache();
 49  499 util_ = util;
 50    }
 51   
 52  185 public Object get(Fqn fqn, Class clazz, PojoInstance pojoInstance)
 53    throws CacheException
 54    {
 55  185 CachedType type = pCache_.getCachedType(clazz);
 56  185 Object obj = null;
 57  185 try
 58    {
 59  185 obj = clazz.newInstance();
 60    // TODO Need to populate the object from the cache as well.
 61    }
 62    catch (Exception e)
 63    {
 64    // Is this a case of no-default constructor, e.g., Enum? Let's try it.
 65  1 try
 66    {
 67  1 obj = loadFromOthers(fqn, clazz);
 68  0 if (obj == null) throw e;
 69    }
 70    catch (Exception e1)
 71    {
 72  0 throw new CacheException("failed creating instance of " + clazz.getName(), e);
 73    }
 74    }
 75    // Insert interceptor at runtime
 76  185 InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
 77  185 CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
 78  185 interceptor.setAopInstance(pojoInstance);
 79  185 util_.attachInterceptor(obj, advisor, interceptor);
 80  185 return obj;
 81    }
 82   
 83  1 private Object loadFromOthers(Fqn fqn, Class clazz) throws Exception
 84    {
 85    // Try Enum first.
 86  1 if (clazz.isEnum())
 87    {
 88  1 String name = (String) pCache_.getCache().get(fqn, InternalConstant.ENUM_KEY);
 89  1 if (name == null)
 90    {
 91  0 throw new CacheException(
 92    "AdvisedPojoHandler.loadFromOthers(): can't retrieve java.lang.Enum name field."
 93    + " fqn: " + fqn);
 94    }
 95  1 Object obj = Enum.valueOf(clazz, name);
 96  1 return obj;
 97    }
 98   
 99  0 return null;
 100    }
 101   
 102  2269 void put(Fqn fqn, Fqn referencingFqn, Object obj) throws CacheException
 103    {
 104  2269 CachedType type = pCache_.getCachedType(obj.getClass());
 105    // We have a clean slate then.
 106  2269 InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
 107    // TODO workaround for deserialiased objects
 108  2269 if (advisor == null)
 109    {
 110  0 advisor = new ClassInstanceAdvisor(obj);
 111  0 ((Advised) obj)._setInstanceAdvisor(advisor);
 112    }
 113   
 114    // Let's do batch update via Map instead
 115  2269 Map map = new HashMap();
 116    // Always initialize the ref count so we can mark this as an AopNode.
 117  2269 PojoInstance pojoInstance = InternalHelper.initializeAopInstance(referencingFqn);
 118  2269 map.put(PojoInstance.KEY, pojoInstance);
 119  2269 pojoInstance.setPojoClass(type.getType());
 120    // we will do it recursively.
 121    // Map of sub-objects that are non-primitive
 122  2269 Map subPojoMap = new HashMap();
 123  2269 boolean hasFieldAnnotation = hasAnnotation(obj.getClass(), ((Advised) obj)._getAdvisor(), type);
 124   
 125  2269 for (Iterator i = type.getFields().iterator(); i.hasNext();)
 126    {
 127  12016 Field field = (Field) (((FieldPersistentReference) i.next())).get();
 128  12016 Object value = null;
 129  12016 try
 130    {
 131  12016 value = field.get(obj);
 132    }
 133    catch (IllegalAccessException e)
 134    {
 135  0 throw new CacheException("field access failed", e);
 136    }
 137  12016 CachedType fieldType = pCache_.getCachedType(field.getType());
 138    // check for non-replicatable types
 139  12016 if (CachedType.isPrimitiveNonReplicatable(field))
 140    {
 141  0 continue;
 142    }
 143   
 144  12016 if (hasFieldAnnotation)
 145    {
 146  6 if (CachedType.hasTransientAnnotation(field, ((Advised) obj)._getAdvisor()))
 147    {
 148  2 continue;
 149    }
 150    }
 151   
 152    // we simply treat field that has @Serializable as a primitive type.
 153  12014 if (fieldType.isImmediate() ||
 154    (hasFieldAnnotation &&
 155    CachedType.hasSerializableAnnotation(field, ((Advised) obj)._getAdvisor())))
 156    {
 157    // switched using batch update
 158  5360 map.put(field.getName(), value);
 159    }
 160    else
 161    {
 162  6654 subPojoMap.put(field, value);
 163    }
 164    }
 165   
 166    // Use option to skip locking since we have parent lock already.
 167    // cache_.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
 168   
 169  2269 cache_.getRoot().addChild(fqn).putAll(map);
 170   
 171    // Insert interceptor after PojoInstance has been written to the cache
 172    // This prevents JBCACHE-1078 with pessimistic locking, optimistic is still a problem
 173  2269 CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
 174  2269 interceptor.setAopInstance(pojoInstance);
 175  2269 util_.attachInterceptor(obj, advisor, interceptor);
 176   
 177    // cache_.getInvocationContext().getOptionOverrides().setSuppressLocking(false);
 178    // This is in-memory operation only
 179  2269 InternalHelper.setPojo(pojoInstance, obj);
 180   
 181  2269 for (Object o : subPojoMap.keySet())
 182    {
 183  6654 Field field = (Field) o;
 184  6654 Object value = subPojoMap.get(field);
 185  4565 if (value == null) continue; // really no need to map the POJO.
 186  2089 pCache_.attach(fqn, value, field.getName());
 187    // If it is Collection classes, we replace it with dynamic proxy.
 188    // But we will have to ignore it if value is null
 189  2089 if (value instanceof Map || value instanceof List || value instanceof Set)
 190    {
 191  1239 Object newValue = pCache_.getObject(fqn, field.getName());
 192  1239 util_.inMemorySubstitution(obj, field, newValue);
 193    }
 194    }
 195   
 196    // Need to make sure this is behind put such that obj.toString is done correctly.
 197  2269 if (log.isDebugEnabled())
 198    {
 199  0 log.debug("internalPut(): inserting with fqn: " + fqn);
 200    }
 201    }
 202   
 203  1885 Object remove(Fqn fqn, Object result, Class clazz) throws CacheException
 204    {
 205  1885 CachedType type = pCache_.getCachedType(clazz);
 206  1885 InstanceAdvisor advisor = ((Advised) result)._getInstanceAdvisor();
 207  1885 for (Iterator i = type.getFields().iterator(); i.hasNext();)
 208    {
 209  10268 Field field = (Field) (((FieldPersistentReference) i.next())).get();
 210  10268 CachedType fieldType = pCache_.getCachedType(field.getType());
 211  10268 Object value = null;
 212  10268 if (!fieldType.isImmediate())
 213    {
 214  5780 value = pCache_.detach(fqn, field.getName());
 215   
 216    // Check for Collection. If it is, we need to reset the original reference.
 217  5780 if ((value instanceof Map || value instanceof List || value instanceof Set))
 218    {
 219    // If this Collection class, we are returning the original value already
 220  1309 util_.inMemorySubstitution(result, field, value);
 221    }
 222    }
 223    else
 224    {
 225    // Update last known field state
 226  4488 value = cache_.get(fqn, field.getName());
 227  4488 util_.inMemorySubstitution(result, field, value);
 228    }
 229    }
 230   
 231    // batch remove
 232  1885 cache_.getRoot().getChild(fqn).clearData();
 233    // Determine if we want to keep the interceptor for later use.
 234  1885 CacheFieldInterceptor interceptor = (CacheFieldInterceptor) AopUtil.findCacheInterceptor(advisor);
 235    // Remember to remove the interceptor from in-memory object but make sure it belongs to me first.
 236  1885 if (interceptor != null)
 237    {
 238  1885 if (log.isDebugEnabled())
 239    {
 240  0 log.debug("regularRemoveObject(): removed cache interceptor fqn: " + fqn + " interceptor: " + interceptor);
 241    }
 242  1885 util_.detachInterceptor(advisor, interceptor);
 243    }
 244   
 245  1885 return null; // Not really null though.
 246    }
 247   
 248  2269 private static boolean hasAnnotation(Class clazz, Advisor advisor, CachedType type)
 249    {
 250  2269 return CachedType.hasAnnotation(clazz, advisor, type);
 251    }
 252   
 253    }