Pointcut for method with call of the specific method inside - aspectj

I have method A and method B. I want pointcut to be attached to the method A, only if method B is called in method A.
Is it possible with Aspets? Thank you.
Example:
Aspect Code:
package aspects.unregistrator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import com.core.Item;
public aspect Unregistrator {
pointcut unRegistrated() : within(tasks..*) && call(* find(..));
after() : unRegistrated() {
Item.unregisterAll();
}
}
this will attach point after every call of find() in every method in tasks package
but I need unregisterAll() to be executed after every method that contains find() call, like this:
package tasks.helpers;
public class TableHelper {
public static void clickButtonInCell(final WTable table) {
table.find(SubitemFactory(Element.BUTTON)).click();
Item.unregisterAll();
}

I have just found one way to make this possible using two special keywords of the AspectJ language: thisEnclosingJoinPointStaticPart and thisJoinPointStaticPart. In this way, you need to keep the enclosing join points where the find() method being called (in your case public static void clickButtonInCell(final WTable table)). Then, you need to check each method execution whether the enclosing join point of the find() method is the same as its join point.
For example:
class TableHelper {
public static void clickButtonInCell(final WTable table) {
System.out.println("clickButtonInCell");
table.find();
// Item.unregisterAll() will be called after find()
}
public static void clickButtonInX(final WTable table) {
System.out.println("clickButtonInX");
table.doSomething();
// even if Item.unregisterAll() is matched with this method execution, it will not work
}
}
public aspect Unregistrator {
String enclosedJP = "";
pointcut unRegistrated() : within(tasks..*) && call(* find(..));
after() : unRegistrated() {
enclosedJP = thisEnclosingJoinPointStaticPart.toLongString();
}
pointcut doPointcut(): within(tasks..*) && execution(* *(..));
after() : doPointcut(){
if(enclosedJP.equals(thisJoinPointStaticPart.toLongString()))
Item.unregisterAll();
}
}
I hope this helps what you need.

Related

AspectJ advice on method of a class that has a field

I want to write an around advice to set a correlation-id into MDC before the invocation of proceed() and return the old value after it. Here is how far I got:
public aspect CorrelationIdAspect
{
private pointcut notPrivateMethod() :
execution(!private * *(..));
private pointcut methodWithContract(Contract contract) :
execution( * *.*(Contract, ..)) && args(contract, ..);
Object around(Contract contract) : methodWithContract(contract) && notPrivateMethod()
{
String oldCorrelationId = MDC.get(Constants.CORRELATION_ID);
try
{
String id = contract.getId().toString();
MDC.put(Constants.CORRELATION_ID, id);
Object result = proceed(contract);
return result;
}
finally
{
MDC.put(Constants.CORRELATION_ID, oldCorrelationId);
}
}
}
Now I want that this advice should only be applied to classes that have a field of type
org.apache.logging.log4j.Logger
because - obviously - a class that has no logger doesn't need to have the correlation id set and restored. Has anybody an idea how that can be accomplished?
Many thanks in advance!
You want to use compiler option -XhasMember (see also my other answer), to be found in Eclipse here:
Then you
add a marker interface to your aspect,
use ITD in order to declare that each class having a static Logger field ought to implement that interface and
match on the marker interface and all its implementing classes:
public aspect CorrelationIdAspect {
// 1. marker interface
private interface HasLogger {}
// 2. use ITD in order to declare that each class having a
// 'static Logger' field ought to implement that interface
declare parents :
hasfield(static Logger *) implements HasLogger;
private pointcut notPrivateMethod() :
execution(!private * *(..));
// 3. match on the marker interface and all its implementing classes
private pointcut hasLogger() :
within(HasLogger+);
private pointcut methodWithContract(Contract contract) :
execution(* *(Contract, ..)) && args(contract, ..);
Object around(Contract contract) :
methodWithContract(contract) && notPrivateMethod() && hasLogger()
{
System.out.println(thisJoinPoint);
return proceed(contract);
}
}

Find direct & indirect method usages if method is overriden in base class

please, help me to figure out how to write the query :)
The code is:
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
var man = new Man("Joe");
Console.WriteLine(man.ToString());
}
}
public class SuperMan
{
public SuperMan(string name)
{
this.name = name;
}
public override string ToString()
{
return name;
}
string name;
}
public class Man : SuperMan
{
public Man(string name) : base(name)
{
}
}
}
I want to find all direct and indirect dependencies (methods) to Man.ToString(). There is only one call in Main() method.
The query I'm trying is:
from m in Methods
let depth0 = m.DepthOfIsUsing("ConsoleApplication1.SuperMan.ToString()")
where depth0 >= 0 orderby depth0
select new { m, depth0 }.
but it doesn't find dependent Program.Main() method....
How to modify query so that it finds usages for such kind of methods?
First let's look at direct callers. We want to list all methods that calls SuperMan.ToString() or any ToString() methods overriden by SuperMan.ToString(). It can looks like:
let baseMethods = Application.Methods.WithFullName("ConsoleApplication1.SuperMan.ToString()").Single().OverriddensBase
from m in Application.Methods.UsingAny(baseMethods)
where m.IsUsing("ConsoleApplication1.Man") // This filter can be added
select new { m, m.NbLinesOfCode }
Notice we put a filter clause, because in the real world pretty much every method calls object.ToString() (this is a particular case).
Now to handle indirect calls this is more tricky. We need to call the magic FillIterative() extension methods on generic sequences.
let baseMethods = Application.Methods.WithFullName("ConsoleApplication1.SuperMan.ToString()").Single().OverriddensBase
let recursiveCallers = baseMethods.FillIterative(methods => methods.SelectMany(m => m.MethodsCallingMe))
from pair in recursiveCallers
let method = pair.CodeElement
let depth = pair.Value
where method.IsUsing("ConsoleApplication1.Man") // Still same filter
select new { method , depth }
Et voilà!

Override TestNG's getTestName method

I execute a TestNG test using a dataProvider.
So I set the testName via #BeforeMethod and I override getTestName().
This works so far, but it seems TestNG is calling the test's getTestName in the beginning
before it starts. This happens when an exception was thrown during configuration, so the #BeforeMethod is not executed and therefore my test name is null.
Is there anyway to call the original method, the one that would have been called if I would not have overwritten it :D since I implement an interface an do not extend from another class I cannot use super.getTestName().
Any way to solve this may be?
#Test(groups = {TestGroups.READY}, description = "check help on each tab")
public class HelpTest extends TestControl implements ITest {
// overriding to return my individual testname, but is null at the beginning
#Override
public String getTestName() {
return TestControl.getCurrentTestName();
}
#DataProvider(name = "tabs")
public Iterator<Object[]> tabs() {
Set<Object[]> list = new LinkedHashSet<Object[]>();
for (Tab tab : Tab.values()) {
list.add(new Object[]{tab});
}
return list.iterator();
}
// before the test below starts, i set my individual testname
#BeforeMethod
public void setTestName(Method method, Object[] testData) {
TestControl.setCurrentTestName(method.getName() + "_" + StringUtils.capitalize(testData[0].toString().toLowerCase()));
}
// executing the test with the given data provider
#Test(dataProvider = "tabs")
public void testHelpSites(Tab tab) throws Exception {
TestActions.goTab(tab).callHelp(tab).checkHelp();
}
}
I guess I figured it out, I also use a TestReporter via AbstractWebDriverEventListener and ITestListener and on its onTestStart(ITestResult result) it's calling the test's name and that's the source of the call before the #BeforeMethod call.
I solved it by checking if result.getName() is null, which calls the test's getTestName() if it implements ITest and if it's null I use the original name from result.getMethod.getMethodName(). Not pretty, but rare :D
I could solve this problem using ITestNGMethod testng class.
ITestNGMethod method = result.getMethod(); // result is ITestResult Object
method.getMethodName(); // This will return method name.
My complete method here:
#Override
public void onTestSuccess(ITestResult result) {
ITestNGMethod method = result.getMethod();
String message = "Test Execution is Successful:"+method.getMethodName();
}
Hope this helps

AspectJ: How to pick the execution of non-annotated methods of subclasses of a given class?

I'd like to intercept the execution of non-annotated methods of any subclass of a given class.
For instance, say I have class Base:
public class Base {
public void baseMethod() { //shouldn't be intercepted
// do whatever...
}
}
And, eventually, someone extends Base. Whatever is the new class name, its methods with some annotation #LeaveItAlone should not be intercepted. All the other methods of the subclass should.
public class Sub extends Base {
public void interceptedMethod1() {
// ...
}
public void interceptedMethod2() {
// ...
}
#LeaveItAlone
public void NOTinterceptedMethod1() {
// ...
}
#LeaveItAlone
public void NOTinterceptedMethod2() {
// ...
}
I imagine something like:
pointcut sub_nonannotated() : !execution(#LeaveItAlone * Base+.*(..));
But I'm certain the above is wrong.
Side question: how do I intercept specifically the constructor of the subclass?
Actually I just tried it and you apparently have it almost correct. This is what worked for me:
package com.snaphop.ats.util;
public aspect Blah {
pointcut sub_nonannotated() : !execution(#LeaveItAlone * Base+.*(..));
pointcut sub() : execution(* Base+.*(..));
pointcut notBase() : ! execution(* Base.*(..));
pointcut cons() : execution(public Base+.new(..)) && ! execution(public Base.new(..));
//advice sub class methods but not annotation or parent
Object around() : sub_nonannotated() && sub() && notBase() {
return proceed();
}
//Advice subclass constructors but not Base's constructor
Object around() : cons() {
return proceed();
}
}
Adam Gent's solution is way too complex. This pointcut is simpler and clearer:
execution(!#LeaveItAlone * Base+.*(..))
Or alternatively, maybe you like it better (a matter of taste):
execution(* Base+.*(..)) && !#annotation(LeaveItAlone)
P.S.: This only takes care of methods, not of constructors, which is what you asked for in your first sentence. I also includes methods of Base itself, not just subclasses, which probably makes sense. If you wanted a more complex thing, you can still combine my solution with the elements from Adam's.

How to call java method from javascript method that located within another jsni method

public class A{
private void javaMethod(int a,int b){}
private native void init()/*-{
function OnMouseMove(e) {
//blow calling doesn't work
this.#p::javaMethod(Ljava/...teger;Ljava.../Integer;)(intVal,intVal);
}
}-*/;
}
As described above,how to make that invoking work?
Answered on the Google Group: https://groups.google.com/d/msg/google-web-toolkit/qE2-L4u_t4s/YqjOu-bUfsAJ
Copied here for reference and convenience:
First, int is not java.lang.Integer, so your method signature in JSNI is wrong; it should read javaMethod(II).
(I suppose the #p:: while javaMethod is defined in class A is over-simplification in your question, but is OK in your code)
You'll also probably have a problem with this, that might not be what you think it is. A common pattern is to assign the current object (this, at the time) to a variable that you'll reference from your closure:
var that = this;
…
function OnMouseMove(e) {
that.#p.A::javaMethod(II)(intVal, intVal);
}
You're doing two things wrong:
You're not defining the class name after #p, (assuming #p is actually just a shortened version of the real package's name);
You're attempting to pass java.lang.Integer in place of int. You should be saying (II) as the types, as described here.
Your code should look more like this:
package com.my.package;
public class ClassA {
private static void javaMethod(int a, int b) { ... }
public static native void init() /*-{
$wnd.javaMethod = function(a, b) {
return #com.my.package.ClassA::javaMethod(II)(a,b);
}
function OnMouseMove(e) {
$wnd.javaMethod(a,b);
}
}-*/;
}