public void testInsertLocal() throws Exception { CtClass cc = sloader.get("test2.InsertLocal"); CtMethod m1 = cc.getDeclaredMethod("foo"); m1.insertBefore("{ i = s.length(); d = 0.14; }"); m1.insertAfter("{ field = i; }"); CtMethod m2 = cc.getDeclaredMethod("run2"); m2.insertAt(22, "{ s = \"12\"; k = 5; }"); CtMethod m3 = cc.getDeclaredMethod("run3"); m3.instrument( new ExprEditor() { public void edit(NewExpr n) throws CannotCompileException { n.replace("{ i++; $_ = $proceed($$); }"); } public void edit(FieldAccess f) throws CannotCompileException { f.replace("{ i++; $_ = $proceed($$); }"); } public void edit(MethodCall m) throws CannotCompileException { m.replace("{ i++; $_ = $proceed($$); }"); } }); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(317, invoke(obj, "run")); assertEquals(7, invoke(obj, "run2")); assertEquals(3, invoke(obj, "run3")); }
public void testCodeGen() throws Exception { CtClass cc = sloader.get("test2.CodeGen"); CtMethod m1 = cc.getDeclaredMethod("run"); m1.insertBefore( "{ double d = true ? 1 : 0.1; " + " d = d > 0.5 ? 0.0 : - 1.0; " + " System.out.println(d); " + " String s = \"foo\"; " + " s = 1 + 2 + s + \"bar\"; " + " s += \"poi\" + 3 + seven() + seven(\":\" + ' '); " + " s += .14; " + " msg = s; " + " System.out.println(s); }"); // recursive type check is done if $proceed is used. CtMethod m2 = CtNewMethod.make( "public int test() {" + " String s = $proceed(\"int\" + (3 + 0.14)) + '.'; " + " System.out.println(s); return s.length(); }", cc, "this", "seven"); cc.addMethod(m2); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(19, invoke(obj, "run")); assertEquals(9, invoke(obj, "test")); }
public void testAddLocalVar() throws Exception { CtClass cc = sloader.get("test2.AddLocalVar"); CtMethod m1 = cc.getDeclaredMethod("foo"); m1.addLocalVariable("i", CtClass.intType); m1.insertBefore("i = 3;"); m1.insertAfter("$_ = i + 1;"); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(4, invoke(obj, "foo")); }
public void testLocalVar() throws Exception { CtClass cc = sloader.get("test2.LocalVar"); CtMethod m = cc.getDeclaredMethod("toString"); m.addLocalVariable("var", CtClass.booleanType); m.insertBefore("{var = true; }"); m.insertAfter("{if (var) hashCode(); }", false); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(3, invoke(obj, "foo")); }
private void preprocessMethods(CtClass cc, boolean insertLoad, boolean wrapFieldAccess) throws CannotCompileException { CtMethod[] methods = cc.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { CtMethod m = methods[i]; if (wrapFieldAccess) { m.instrument( new ExprEditor() { public void edit(FieldAccess fa) throws CannotCompileException { try { if ((fa.getField().getModifiers() & (Modifier.TRANSIENT | Modifier.STATIC)) == 0 && fa.getField().getDeclaringClass().subtypeOf(persistentInterface)) { if (fa.isWriter()) { fa.replace("{ $0.loadAndModify(); $proceed($$); }"); } // isSelfReader is my extension of JAssist, if you // use original version of JAssist comment the // branch below or replace "else if" with "else". // In first case Perst will not be able to handle // access to foreign (non-this) fields. You should use // getter/setter methods instead. // In second case access to foreign fields still will be possible, // but with significant degradation of performance and // increased code size, because in this case before ALL access // to fields of persistent capable object call of load() method // will be inserted. else if (!fa.isSelfReader()) { fa.replace("{ $0.load(); $_ = $proceed($$); }"); } } } catch (NotFoundException x) { } } }); } if (insertLoad && !"recursiveLoading".equals(m.getName()) && (m.getModifiers() & (Modifier.STATIC | Modifier.ABSTRACT)) == 0) { m.insertBefore("load();"); } } }