Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 217   Methods: 13
NCLOC: 159   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CacheFieldInterceptor.java 87.5% 85.1% 69.2% 83.9%
coverage coverage
 1    /*
 2    * JBoss, the OpenSource J2EE webOS
 3    *
 4    * Distributable under LGPL license.
 5    * See terms of license at gnu.org.
 6    */
 7    package org.jboss.cache.pojo.interceptors.dynamic;
 8   
 9    import java.lang.reflect.Field;
 10   
 11    import org.apache.commons.logging.Log;
 12    import org.apache.commons.logging.LogFactory;
 13    import org.jboss.aop.Advisor;
 14    import org.jboss.aop.advice.Interceptor;
 15    import org.jboss.aop.joinpoint.FieldInvocation;
 16    import org.jboss.aop.joinpoint.FieldReadInvocation;
 17    import org.jboss.aop.joinpoint.FieldWriteInvocation;
 18    import org.jboss.aop.joinpoint.Invocation;
 19    import org.jboss.aop.joinpoint.MethodInvocation;
 20    import org.jboss.cache.Cache;
 21    import org.jboss.cache.Fqn;
 22    import org.jboss.cache.pojo.PojoCacheAlreadyDetachedException;
 23    import org.jboss.cache.pojo.impl.CachedType;
 24    import org.jboss.cache.pojo.impl.PojoCacheImpl;
 25    import org.jboss.cache.pojo.impl.PojoInstance;
 26    import org.jboss.cache.pojo.impl.PojoUtil;
 27    import org.jboss.cache.pojo.util.ObjectUtil;
 28   
 29    /**
 30    * Main dynamic interceptor to intercept for field replication.
 31    *
 32    * @author Ben Wang
 33    */
 34   
 35    public class CacheFieldInterceptor implements BaseInterceptor
 36    {
 37    private final Log log_ = LogFactory.getLog(CacheFieldInterceptor.class);
 38    Cache<Object, Object> cache_;
 39    private PojoCacheImpl pCache_;
 40    Fqn fqn_;
 41    private String name_;
 42    private PojoInstance pojoInstance_;
 43    private PojoUtil util_;
 44   
 45  2454 public CacheFieldInterceptor(PojoCacheImpl pCache, Fqn fqn, CachedType type)
 46    {
 47  2454 this.pCache_ = pCache;
 48  2454 this.cache_ = pCache_.getCache();
 49  2454 this.fqn_ = fqn;
 50  2454 util_ = new PojoUtil();
 51    }
 52   
 53  0 public CacheFieldInterceptor()
 54    {
 55    }
 56   
 57  1931 public PojoInstance getAopInstance()
 58    {
 59  1931 return pojoInstance_;
 60    }
 61   
 62  0 public Object clone()
 63    {
 64  0 BaseInterceptor interceptor = new CacheFieldInterceptor();
 65  0 interceptor.setFqn(getFqn());
 66  0 interceptor.setAopInstance(getAopInstance());
 67  0 return interceptor;
 68    }
 69   
 70  0 public void setInterceptor(Interceptor intcptr)
 71    {
 72  0 BaseInterceptor interceptor = (BaseInterceptor) intcptr;
 73  0 setFqn(interceptor.getFqn());
 74  0 setAopInstance(interceptor.getAopInstance());
 75    }
 76   
 77  2454 public void setAopInstance(PojoInstance pojoInstance)
 78    {
 79  2454 this.pojoInstance_ = pojoInstance;
 80    }
 81   
 82  3832 public String getName()
 83    {
 84  3832 if (name_ == null)
 85    {
 86  1904 this.name_ = "CacheFieldInterceptor on [" + fqn_ + "]";
 87    }
 88  3832 return name_;
 89    }
 90   
 91  2518 public Object invoke(Invocation invocation) throws Throwable
 92    {
 93    // Kind of ad hoc now. MethodInvocation should not invoke this.
 94  2518 if (invocation instanceof MethodInvocation)
 95  0 return invocation.invokeNext();
 96   
 97   
 98  2518 if (invocation instanceof FieldWriteInvocation)
 99    {
 100  412 FieldInvocation fieldInvocation =
 101    (FieldInvocation) invocation;
 102   
 103  412 Advisor advisor = fieldInvocation.getAdvisor();
 104  412 Field field = fieldInvocation.getField();
 105  412 if (log_.isTraceEnabled())
 106    {
 107  0 log_.trace("invoke(): field write interception for fqn: " + fqn_ + " and field: " + field);
 108    }
 109   
 110  412 verifyAttached(invocation.getTargetObject());
 111   
 112    // Only if this field is replicatable. static, transient and final are not.
 113  411 CachedType fieldType = pCache_.getCachedType(field.getType());
 114  411 CachedType parentType = pCache_.getCachedType(field.getDeclaringClass());
 115  411 Object value = ((FieldWriteInvocation) fieldInvocation).getValue();
 116  411 if (!isNonReplicatable(field, advisor, parentType))
 117    {
 118  408 if (fieldType.isImmediate() || hasSerializableAnnotation(field, advisor, parentType))
 119    {
 120  118 cache_.put(fqn_, field.getName(), value);
 121    }
 122    else
 123    {
 124  290 pCache_.attach(fqn_, value, field.getName());
 125    }
 126    }
 127   
 128  411 Object obj = fieldInvocation.getTargetObject();
 129  411 util_.inMemorySubstitution(obj, field, value);
 130    }
 131  2106 else if (invocation instanceof FieldReadInvocation)
 132    {
 133  2106 FieldInvocation fieldInvocation =
 134    (FieldInvocation) invocation;
 135  2106 Field field = fieldInvocation.getField();
 136  2106 Advisor advisor = fieldInvocation.getAdvisor();
 137   
 138    // Only if this field is replicatable
 139  2106 CachedType fieldType = pCache_.getCachedType(field.getType());
 140  2106 CachedType parentType = pCache_.getCachedType(field.getDeclaringClass());
 141  2106 if (!isNonReplicatable(field, advisor, parentType))
 142    {
 143  2066 Object result;
 144  2066 if (fieldType.isImmediate() || hasSerializableAnnotation(field, advisor, parentType))
 145    {
 146  1211 result = cache_.get(fqn_, field.getName());
 147    }
 148    else
 149    {
 150  855 result = pCache_.getObject(fqn_, field.getName());
 151    }
 152   
 153    // If the result is null, the object might have been detached
 154  2063 if (result == null)
 155  160 verifyAttached(invocation.getTargetObject());
 156   
 157    // Update last known state associated with this pojo.
 158  2061 util_.inMemorySubstitution(invocation.getTargetObject(), field, result);
 159   
 160    // Allow interceptor chain to process, but ignore the result
 161  2061 invocation.invokeNext();
 162   
 163  2061 return result;
 164    }
 165    }
 166   
 167  451 return invocation.invokeNext();
 168    }
 169   
 170    /**
 171    * See if this field is non-replicatable such as @Transient or transient modifier.
 172    */
 173  2517 private static boolean isNonReplicatable(Field field, Advisor advisor, CachedType type)
 174    {
 175  2517 if (CachedType.hasAnnotation(field.getDeclaringClass(), advisor, type))
 176    {
 177  2 if (CachedType.hasTransientAnnotation(field, advisor)) return true;
 178    }
 179   
 180  41 if (CachedType.isPrimitiveNonReplicatable(field)) return true;
 181   
 182  2474 return false;
 183    }
 184   
 185  1149 private static boolean hasSerializableAnnotation(Field field, Advisor advisor, CachedType type)
 186    {
 187  1149 if (CachedType.hasAnnotation(field.getDeclaringClass(), advisor, type))
 188    {
 189  4 if (CachedType.hasSerializableAnnotation(field, advisor)) return true;
 190    }
 191   
 192  1145 return false;
 193    }
 194   
 195    /**
 196    * Check if the pojo is detached already.
 197    */
 198  572 private void verifyAttached(Object target)
 199    {
 200  572 if (cache_.get(fqn_, PojoInstance.KEY) != null)
 201  569 return;
 202   
 203  3 String identity = ObjectUtil.identityString(target);
 204  3 throw new PojoCacheAlreadyDetachedException(identity + " has possibly been detached remotely. Internal id: " + fqn_);
 205    }
 206   
 207  322 public Fqn getFqn()
 208    {
 209  322 return fqn_;
 210    }
 211   
 212  0 public void setFqn(Fqn fqn)
 213    {
 214  0 this.fqn_ = fqn;
 215    }
 216   
 217    }