package kr.ac.snu.selab.soot.analyzer; import java.util.HashSet; import java.util.Map; import java.util.Set; import kr.ac.snu.selab.soot.graph.MetaInfo; import soot.Hierarchy; import soot.SootClass; import soot.SootMethod; import soot.jimple.toolkits.callgraph.CallGraph; public class ObserverPattern extends PatternAnalysis { public PatternAnalysisResult perform(Map<String, SootClass> classMap, Hierarchy hierarchy, CallGraph cg, AnalysisUtil au) { PatternAnalysisResult result = new PatternAnalysisResult(); result.hierarchy(hierarchy); result.setPatternName("Observer"); Set<SootClass> interfaceTypes = au.interfaceTypes(classMap); for (SootClass interfaceType : interfaceTypes) { RoleRepository roles = new RoleRepository(); Map<String, MetaInfo> metaInfoMap = au.metaInfoMap(classMap.values()); //Set<Path<MetaInfo>> abstractReferenceFlows = new HashSet<Path<MetaInfo>>(); //abstractReferenceFlows = au.abstractReferenceFlows(interfaceType, classMap, hierarchy, cg, metaInfoMap, roles); //result.addReferenceFlowsPerType(interfaceType, abstractReferenceFlows); au.analyzeRole(interfaceType, metaInfoMap, roles, classMap, hierarchy, cg); Map<SootClass, Set<SootClass>> superClassMap = au.superClassMap(classMap, hierarchy); for (MetaInfo metaInfoOfCaller : roles.callers()) { for (Role role : metaInfoOfCaller.callers()) { Caller caller = (Caller)role; SootClass callerClass = caller.declaringClass(); SootMethod calledMethod = caller.calledMethod(); if (au.doesHaveCollection(callerClass, superClassMap)) { if (calledMethod.getParameterCount() == 1) { result.addInterfaceType(interfaceType); if (result.rolesPerType().containsKey(interfaceType)) { result.rolesPerType().get(interfaceType).addCaller(metaInfoOfCaller); } else { RoleRepository relatedRoles = new RoleRepository(); relatedRoles.addCaller(metaInfoOfCaller); result.addRoles(interfaceType, relatedRoles); } } else { Set<LocalInfo> delegateInfoSet = new HashSet<LocalInfo>(); delegateInfoSet = au.delegateInfos(calledMethod, classMap, superClassMap); for (LocalInfo delegateInfo : delegateInfoSet) { SootClass delegateType = au.typeToClass(delegateInfo.local().getType(), classMap); if ((delegateType != null) && (au.isSubtypeIncluding(delegateType, callerClass, hierarchy))) { result.addInterfaceType(interfaceType); if (result.rolesPerType().containsKey(interfaceType)) { result.rolesPerType().get(interfaceType).addCaller(metaInfoOfCaller); } else { RoleRepository relatedRoles = new RoleRepository(); relatedRoles.addCaller(metaInfoOfCaller); result.addRoles(interfaceType, relatedRoles); } } } } } } } } return result; } }