package org.ntlab.deltaViewer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.ntlab.deltaExtractor.Alias;
import org.ntlab.deltaExtractor.Alias.AliasType;
import org.ntlab.deltaExtractor.IAliasCollector;
import org.ntlab.trace.ArrayAccess;
import org.ntlab.trace.ArrayCreate;
import org.ntlab.trace.ArrayUpdate;
import org.ntlab.trace.FieldAccess;
import org.ntlab.trace.FieldUpdate;
import org.ntlab.trace.IStatementVisitor;
import org.ntlab.trace.MethodExecution;
import org.ntlab.trace.AbstractTracePointVisitor;
import org.ntlab.trace.MethodInvocation;
import org.ntlab.trace.ObjectReference;
import org.ntlab.trace.Reference;
import org.ntlab.trace.Statement;
import org.ntlab.trace.TracePoint;
public class ForwardAliasCollector extends AbstractTracePointVisitor implements IAliasCollector {
private List<Alias> aliasList = new ArrayList<>();
private FullObjectCallGraph objectCallGraph;
private TracePoint firstTracePoint = null;
public ForwardAliasCollector() {
objectCallGraph = new FullObjectCallGraph();
}
@Override
public boolean preVisitStatement(Statement statement, TracePoint tp) {
if (firstTracePoint == null) {
objectCallGraph.addStartPoint(tp.getMethodExecution());
firstTracePoint = tp.duplicate();
// for MagnetRON
Alias thisAlias = new Alias(AliasType.THIS, 0, tp.getMethodExecution().getThisObjId(), tp.duplicate());
addAlias(thisAlias);
}
if (statement instanceof MethodInvocation) {
MethodInvocation mi = (MethodInvocation) statement;
String methodSignature = mi.getCalledMethodExecution().getSignature();
if (!methodSignature.contains("<clinit>")) {
// Not a class initializer.
if (!mi.getCalledMethodExecution().isConstructor()) {
String receiver = mi.getCalledMethodExecution().getThisObjId();
Alias recerverAlias = new Alias(AliasType.RECEIVER, 0, receiver, tp.duplicate());
addAlias(recerverAlias);
}
int index = 0;
for (ObjectReference arg: mi.getCalledMethodExecution().getArguments()) {
Alias argAlias = new Alias(AliasType.ACTUAL_ARGUMENT, index, arg.getId(), tp.duplicate());
addAlias(argAlias);
index++;
}
if (mi.getCalledMethodExecution().isCollectionType()
&& (methodSignature.contains("add(")
|| methodSignature.contains("set(")
|| methodSignature.contains("put(")
|| methodSignature.contains("push(")
|| methodSignature.contains("addElement("))) {
objectCallGraph.addRelatedPoint(tp.duplicate());
}
index = 0;
for (ObjectReference arg: mi.getCalledMethodExecution().getArguments()) {
Alias argAlias = new Alias(AliasType.FORMAL_PARAMETER, index, arg.getId(), mi.getCalledMethodExecution().getEntryPoint());
addAlias(argAlias);
index++;
}
}
} else if (statement instanceof FieldAccess) {
FieldAccess fa = (FieldAccess) statement;
if (fa.getContainerObjId().equals(fa.getThisObjId())) {
Alias thisAlias = new Alias(AliasType.THIS, 0, fa.getThisObjId(), tp.duplicate());
addAlias(thisAlias);
} else {
Alias containerAlias = new Alias(AliasType.CONTAINER, 0, fa.getContainerObjId(), tp.duplicate());
addAlias(containerAlias);
}
Alias fieldAlias = new Alias(AliasType.FIELD, 0, fa.getValueObjId(), tp.duplicate());
addAlias(fieldAlias);
objectCallGraph.addReference(fa.getReference());
} else if (statement instanceof FieldUpdate) {
FieldUpdate fu = (FieldUpdate) statement;
if (!fu.getValueClassName().equals("---")) {
// Updated by a non-null value.
// if (fu.getContainerObjId().equals(tp.getMethodExecution().getThisObjId())) {
// Alias thisAlias = new Alias(AliasType.THIS, 0, tp.getMethodExecution().getThisObjId(), tp.duplicate());
// addAlias(thisAlias);
// } else {
// Alias containerAlias = new Alias(AliasType.CONTAINER, 0, fu.getContainerObjId(), tp.duplicate());
// addAlias(containerAlias);
// }
objectCallGraph.addRelatedPoint(tp.duplicate());
}
} else if (statement instanceof ArrayCreate) {
ArrayCreate ac = (ArrayCreate) statement;
Alias thisAlias = new Alias(AliasType.THIS, 0, tp.getMethodExecution().getThisObjId(), tp.duplicate());
addAlias(thisAlias);
Alias arrayCreateAlias = new Alias(AliasType.ARRAY_CREATE, 0, ac.getArrayObjectId(), tp.duplicate());
addAlias(arrayCreateAlias);
Reference ref = new Reference(tp.getMethodExecution().getThisObjId(), ac.getArrayObjectId(), tp.getMethodExecution().getThisClassName(), ac.getArrayClassName());
ref.setCreation(true);
objectCallGraph.addReference(ref);
} else if (statement instanceof ArrayAccess) {
ArrayAccess aa = (ArrayAccess) statement;
Alias arrayAlias = new Alias(AliasType.ARRAY, 0, aa.getArrayObjectId(), tp.duplicate());
addAlias(arrayAlias);
Alias arrayElementAlias = new Alias(AliasType.ARRAY_ELEMENT, aa.getIndex(), aa.getValueObjectId(), tp.duplicate());
addAlias(arrayElementAlias);
Reference ref = new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName());
ref.setArray(true);
objectCallGraph.addReference(ref);
} else if (statement instanceof ArrayUpdate) {
ArrayUpdate au = (ArrayUpdate) statement;
Alias arrayAlias = new Alias(AliasType.ARRAY, 0, au.getArrayObjectId(), tp.duplicate());
addAlias(arrayAlias);
objectCallGraph.addRelatedPoint(tp.duplicate());
}
return false;
}
@Override
public boolean postVisitStatement(Statement statement, TracePoint tp) {
if (statement instanceof MethodInvocation) {
MethodInvocation mi = (MethodInvocation) statement;
String returnValue = mi.getCalledMethodExecution().getReturnValue().getId();
String methodSignature = mi.getCalledMethodExecution().getSignature();
if (!methodSignature.contains("<clinit>")) {
// Not a class initializer.
if (!mi.getCalledMethodExecution().isConstructor()) {
if (!mi.getCalledMethodExecution().getReturnValue().getActualType().equals("void")) {
Alias returnAlias = new Alias(AliasType.RETURN_VALUE, 0, returnValue, mi.getCalledMethodExecution().getExitPoint());
addAlias(returnAlias);
Alias methodInvAlias = new Alias(AliasType.METHOD_INVOCATION, 0, returnValue, tp.duplicate());
addAlias(methodInvAlias);
}
if (methodSignature.contains("List.get(") ||
methodSignature.contains("Map.get(")) {
String returnClass = mi.getCalledMethodExecution().getReturnValue().getActualType();
Reference ref = new Reference(mi.getCalledMethodExecution().getThisObjId(), returnValue, mi.getCalledMethodExecution().getThisClassName(), returnClass);
ref.setCollection(true);
objectCallGraph.addReference(ref);
}
} else {
Alias methodInvAlias = new Alias(AliasType.CONSTRACTOR_INVOCATION, 0, returnValue, tp.duplicate());
addAlias(methodInvAlias);
String returnClass = mi.getCalledMethodExecution().getReturnValue().getActualType();
Reference ref = new Reference(tp.getMethodExecution().getThisObjId(), returnValue, tp.getMethodExecution().getThisClassName(), returnClass);
ref.setCreation(true);
objectCallGraph.addReference(ref);
}
}
} else if (statement instanceof FieldAccess) {
} else if (statement instanceof FieldUpdate) {
} else if (statement instanceof ArrayCreate) {
} else if (statement instanceof ArrayAccess) {
} else if (statement instanceof ArrayUpdate) {
}
return false;
}
@Override
public void addAlias(Alias alias) {
aliasList.add(alias);
}
@Override
public List<Alias> getAliasList() {
return aliasList;
}
public IObjectCallGraph getObjectCallGraph() {
return objectCallGraph;
}
private class FullObjectCallGraph implements IObjectCallGraph {
private List<Reference> references = new ArrayList<>();
private List<MethodExecution> startPoints = new ArrayList<>();
private List<TracePoint> relatedPoints = new ArrayList<>();
public void addReference(Reference r) {
if (!references.contains(r)) references.add(r);
}
public void addStartPoint(MethodExecution me) {
startPoints.add(me);
}
public void addRelatedPoint(TracePoint tp) {
relatedPoints.add(tp);
}
@Override
public List<Reference> getReferences() {
return references;
}
@Override
public List<MethodExecution> getStartPoints() {
return startPoints;
}
@Override
public List<TracePoint> getRelatedPoints() {
return relatedPoints;
}
@Override
public Map<MethodExecution, List<MethodExecution>> getCallTree() {
return null;
}
}
}