I am trying to use location specifier for List/Maps. Its not working when adding elements to it via their API.
When I set the variable using =
, it works.
import java.util.*;
public class SimpleTest
{
public static void main(String[] args)
{
System.out.println("Java: Entering main");
for (int i = 1; i <= 1; i++)
{
loopTest(i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println(e);
}
}
}
public static void loopTest(int i)
{
System.out.println("Java: Iteration " + i);
Integer a;
a=new Integer(1);
a=new Integer(2);
a=new Integer(3);
System.out.println("Java: a is " + a);
System.out.println(" *********************** ");
//Creating a List
List<String> list=new ArrayList<String>();
//Adding elements in the List
list.add("Mango");
list.add("Apple");
list.add("Banana");
//Iterating the List element using for-each loop
for(String fruit:list)
{
System.out.println("Java: list is" + fruit);
}
//Re-init list
list=Arrays.asList("foo", "bar");
//Iterating the List element using for-each loop
for(String fruit:list)
{
System.out.println("Java: list (new) is" + fruit);
}
}
}
Byteman rule:
RULE trace main entry
CLASS SimpleTest
METHOD main
AT ENTRY
IF true
DO System.out.println("Byteman detected you are entering main - test")
ENDRULE
RULE catch_SimpleTest.loopTest
CLASS SimpleTest
METHOD loopTest
COMPILE
AT ENTRY
IF true
DO
System.out.println("Byteman Enter loopTest - " + $1)
ENDRULE
RULE catch_SimpleTest.loopTest0
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $a 0
IF true
DO
System.out.println("Byteman loopTest0: " + $a)
ENDRULE
RULE catch_SimpleTest.loopTest1
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $a 1
IF true
DO
System.out.println("Byteman loopTest1: " + $a)
ENDRULE
RULE catch_SimpleTest.loopTest2
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $a 2
IF true
DO
System.out.println("Byteman loopTest2: " + $a)
ENDRULE
RULE catch_SimpleTest.loopTest3
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $a 3
IF true
DO
System.out.println("Byteman loopTest3: " + $a)
ENDRULE
RULE catch_SimpleTest.loopTestALL
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $a ALL
IF true
DO
System.out.println("Byteman loopTestALL: " + $a)
ENDRULE
RULE catch_SimpleTest.loopTestList1
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $list 1
IF true
DO
System.out.println("Byteman loopTestList1: " + $list)
ENDRULE
RULE catch_SimpleTest.loopTestList2
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $list 2
IF true
DO
System.out.println("Byteman loopTestList2: " + $list)
ENDRULE
RULE catch_SimpleTest.loopTestList3
CLASS SimpleTest
METHOD loopTest
COMPILE
AFTER WRITE $list 3
IF true
DO
System.out.println("Byteman loopTestList3: " + $list)
ENDRULE
Byteman output:
I expected after each add operation like list.add("Mango");
etc, a rule should be triggered, but it's not.
As can be seen, when I use =
, again list=Arrays.asList("foo", "bar");
rule is triggered.
It seems =
is the only operator that is seen by Location logic.
You are misunderstanding the AFTER WRITE location specifier. When you specify
AFTER WRITE list
that identifies a place in the code where var is initialized or assigned. So it would match a statement like
List list = new LinkedList()
or
list = new ArrayList(3)
It will not match a statement like
list.add("banana")
because that statement does not initialize or assign a value to variable list.
If you want to trigger a rule when the add method is called you need to specify a call location:
AT CALL add
That will match the first call to method add. You can also include a count
AT CALL add 3
or use the keyword ALL to make your rule match every call to add.