// package lawofDemeter; import java.util.*; import org.aspectj.lang.*; public abstract aspect LawofDemeter_AJ{ //interfaces public interface Checked{ } public interface MethodSupplier{ } public interface FieldSupplier{ } //abstract pointcuts public abstract pointcut Check(Object thiz, Object target); public abstract pointcut NonStaticMethod(Object target); public abstract pointcut StaticMethod(Object thiz); public abstract pointcut Constructor(Object thiz,Object target); public abstract pointcut Set(Object target, Object value); //advice Object around(Object thiz, Object target):Check(thiz, target){ //check the LOD if(!((MethodSupplier)thiz).contains(target) && !((FieldSupplier)thiz).containsSupplier(target)) System.out.println("LoD violation " + thisJoinPoint); Object r = proceed(thiz, target); return r; } Object around(Object target):NonStaticMethod(target){ Object thiz = thisJoinPoint.getThis(); //argument rule Vector v = new Vector(); Object[] args = thisJoinPoint.getArgs(); for(int i=0;i < args.length; i++) v.add(args[i]); HashSet newSet = new HashSet(); newSet.addAll(v); newSet.add(target); MethodSupplier.st.push(newSet); Object r = proceed(target); MethodSupplier.st.pop(); //associate rule: self call if(target == thiz){ HashSet enclosingSet= (HashSet) MethodSupplier.st.peek(); enclosingSet.add(r); } return r; } Object around(Object thiz):StaticMethod(thiz){ //associate rule: a static call HashSet enclosingSet= (HashSet) MethodSupplier.st.peek(); Object r = proceed(thiz); enclosingSet.add(r); return r; } Object around(Object thiz,Object target):Constructor(thiz, target){ // associate rule: call a constructor Object newObj = proceed(thiz, target); HashSet enclosingSet = (HashSet) MethodSupplier.st.peek(); enclosingSet.add(newObj); return newObj; } Object around(Object target, Object value): Set(target, value){ //context insensitive situation Object newObj = proceed(target, value); JoinPoint.StaticPart sp = thisJoinPointStaticPart; String fieldName = sp.getSignature(). getDeclaringType().getName() + ":" + sp.getSignature().getName(); FieldSupplier perTarget = (FieldSupplier) target; if(perTarget.fieldNames.containsKey(fieldName)) fieldName = (String) perTarget.fieldNames.get(fieldName); else perTarget.fieldNames.put(fieldName,fieldName); perTarget.targets.put(fieldName, value); return newObj; } // MethodSupplier private static Stack MethodSupplier.st = new Stack(); public boolean MethodSupplier.contains(Object target){ HashSet enclosingSet= (HashSet) st.peek(); return enclosingSet.contains(target); } //PartSupplier private HashMap FieldSupplier.targets = new HashMap(); private HashMap FieldSupplier.fieldNames = new HashMap(); public boolean FieldSupplier.containsSupplier(Object supplier){ return targets.containsValue(supplier); } }