.v()
.loadClassAndSupport("java.net.URI");
RefType type = RefType.v(uriClass);
SootMethod initMethod = uriClass
.getMethod("void <init>(java.lang.String)");
Local local = (Local) ((AssignStmt) unit)
.getLeftOp();
String uriString = URIAttribute
.getModelURI(_model).toString();
body
.getUnits()
.insertBefore(
Jimple
.v()
.newAssignStmt(
local,
Jimple
.v()
.newNewExpr(
type)),
unit);
body
.getUnits()
.insertBefore(
Jimple
.v()
.newInvokeStmt(
Jimple
.v()
.newSpecialInvokeExpr(
local,
initMethod
.makeRef(),
StringConstant
.v(uriString))),
unit);
}
body.getUnits().remove(unit);
} else if (expr
.getMethod()
.getSubSignature()
.equals(
PtolemyUtilities.handleModelErrorMethod
.getSubSignature())) {
// Replace handleModelError with a throw clause.
body.getUnits()
.insertBefore(
Jimple.v().newThrowStmt(
expr.getArg(1)), unit);
body.getUnits().remove(unit);
}
}
}
}
}
}
List modifiedConstructorClassList = new LinkedList();
// Loop over all the classes
for (Iterator i = Scene.v().getApplicationClasses().iterator(); i
.hasNext();) {
SootClass theClass = (SootClass) i.next();
if (SootUtilities
.derivesFrom(theClass, PtolemyUtilities.actorClass)
|| SootUtilities.derivesFrom(theClass,
PtolemyUtilities.compositeActorClass)
|| SootUtilities.derivesFrom(theClass,
PtolemyUtilities.attributeClass)) {
System.out.println("changing superclass for " + theClass);
theClass.setSuperclass(PtolemyUtilities.objectClass);
// Fix the constructor for the actor to take just a
// container argument, if it was a 2 arg constructor,
// or no arguments otherwise. FIXME: Here we assume
// that there is just one constructor.. This will
// throw an exception if there is more than one, in
// which case we need to improve this code.
SootMethod method = null;
try {
method = theClass.getMethodByName("<init>");
} catch (RuntimeException ex) {
System.out.println("Could not get method <init> by name "
+ "from class " + theClass);
System.out.println("Methods = " + theClass.getMethods());
throw ex;
}
if (method.getParameterCount() == 2) {
// Change the constructor so that it only takes the container.
SootField containerField = theClass
.getFieldByName(ModelTransformer
.getContainerFieldName());
RefType containerType = (RefType) containerField.getType();
List typeList = new LinkedList();
typeList.add(containerType);
method.setParameterTypes(typeList);
} else {
method.setParameterTypes(Collections.EMPTY_LIST);
}
// Keep track of the modification, so we know to
// modify invocations of that constructor.
modifiedConstructorClassList.add(theClass);
// Dance so that indexes in the Scene are properly updated.
theClass.removeMethod(method);
theClass.addMethod(method);
System.out.println("method = " + method);
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
for (Iterator units = body.getUnits().snapshotIterator(); units
.hasNext();) {
Stmt unit = (Stmt) units.next();
if (unit.containsInvokeExpr()) {
ValueBox box = unit.getInvokeExprBox();
Value value = box.getValue();
if (value instanceof SpecialInvokeExpr) {
// Fix super.<init> calls. constructor...
SpecialInvokeExpr expr = (SpecialInvokeExpr) value;
if (expr.getBase().equals(body.getThisLocal())
&& expr.getMethodRef().name().equals(
"<init>")) {
// System.out.println("replacing constructor = "
// + unit + " in method " + method);
// Replace with zero arg object constructor.
box.setValue(Jimple.v().newSpecialInvokeExpr(
(Local) expr.getBase(),
PtolemyUtilities.objectConstructor
.makeRef(),
Collections.EMPTY_LIST));
}
}
} else if (unit instanceof IdentityStmt) {
IdentityStmt identityStmt = (IdentityStmt) unit;
Value value = identityStmt.getRightOp();
if (value instanceof ParameterRef) {
ParameterRef parameterRef = (ParameterRef) value;
if ((parameterRef.getIndex() == 0)
&& (method.getParameterCount() == 1)) {
// System.out.println("found = " + identityStmt);
ValueBox box = identityStmt.getRightOpBox();
box.setValue(Jimple.v().newParameterRef(
method.getParameterType(0), 0));
// System.out.println("changed to: " + identityStmt);
} else {
// Parameter values are null. Note that
// we need to make sure that the
// assignment to null happens after all
// the identity statements, otherwise the
// super constructor will be implicitly
// called.
body.getUnits().remove(identityStmt);
body.getUnits().insertBefore(
Jimple.v().newAssignStmt(
identityStmt.getLeftOp(),
NullConstant.v()),
body.getFirstNonIdentityStmt());
}
} // else if (value instanceof ThisRef) {
// // Fix the type of thisRefs.
// ValueBox box = identityStmt.getRightOpBox();
// box.setValue(
// Jimple.v().newThisRef(
// RefType.v(PtolemyUtilities.objectClass)));
// }
}
}
}
}
// Reset the hierarchy, since we've changed superclasses and such.
Scene.v().setActiveHierarchy(new Hierarchy());
Scene.v().setFastHierarchy(new FastHierarchy());
// Fix the specialInvokes.
for (Iterator i = Scene.v().getApplicationClasses().iterator(); i
.hasNext();) {
SootClass theClass = (SootClass) i.next();
// Loop through all the methods in the class.
for (Iterator methods = theClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
// System.out.println("method = " + method);
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
for (Iterator units = body.getUnits().snapshotIterator(); units
.hasNext();) {
Stmt unit = (Stmt) units.next();
if (unit.containsInvokeExpr()) {
ValueBox box = unit.getInvokeExprBox();
Value value = box.getValue();
if (value instanceof SpecialInvokeExpr) {
// If we're constructing one of our actor classes,
// then switch to the modified constructor.
SpecialInvokeExpr expr = (SpecialInvokeExpr) value;
SootClass declaringClass = expr.getMethodRef()
.declaringClass();
if (expr.getMethodRef().name().equals("<init>")
&& modifiedConstructorClassList
.contains(declaringClass)) {
System.out
.println("replacing constructor invocation = "
+ unit + " in method " + method);
SootMethod newConstructor = declaringClass
.getMethodByName("<init>");
if (newConstructor.getParameterCount() == 1) {
// Replace with just container arg constructor.
List args = new LinkedList();
args.add(expr.getArg(0));
box.setValue(Jimple.v()
.newSpecialInvokeExpr(
(Local) expr.getBase(),
newConstructor.makeRef(),
args));
} else {
// Replace with zero arg constructor.
box.setValue(Jimple.v()
.newSpecialInvokeExpr(
(Local) expr.getBase(),
newConstructor.makeRef(),
Collections.EMPTY_LIST));
}
}
}
}
}
}
}
for (Iterator i = Scene.v().getApplicationClasses().iterator(); i
.hasNext();) {
SootClass theClass = (SootClass) i.next();
// Loop through all the methods in the class.
for (Iterator methods = theClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
// System.out.println("method = " + method);
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
// Infer types.
LocalSplitter.v().transform(body, "nee.ls");
TypeAssigner.v().transform(body, "nee.ta");
}
}
for (Iterator i = Scene.v().getApplicationClasses().iterator(); i
.hasNext();) {
SootClass theClass = (SootClass) i.next();
// Loop through all the methods in the class.
for (Iterator methods = theClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
// System.out.println("method = " + method);
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
for (Iterator units = body.getUnits().snapshotIterator(); units
.hasNext();) {
Stmt unit = (Stmt) units.next();
// System.out.println("unit = " + unit);
// If any box is removable, then remove the statement.
for (Iterator boxes = unit.getUseAndDefBoxes().iterator(); boxes
.hasNext();) {
ValueBox box = (ValueBox) boxes.next();
Value value = box.getValue();
Type type = value.getType();
if (_isRemovableType(type)) {
// System.out.println("Unit with removable type "
// + type + ": " + unit);
body.getUnits().remove(unit);
break;
}
}
// If any locals are removable, then remove them.
for (Iterator locals = body.getLocals().snapshotIterator(); locals
.hasNext();) {
Local local = (Local) locals.next();
Type type = local.getType();
if (_isRemovableType(type)) {
body.getLocals().remove(local);
}
}