AspectJ advice on method of a class that has a field - aspectj

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);
}
}

Related

Add my own rules in SonarQube with RPG

I want to create my own SonarQube Plugin for the RPG language. I have the following problem.
I start by created the RpgLanguage class that extends to AbstractLanguage. In this class, I defined my new language "Rpg". You can see my class in the following code :
public class RpgLanguage extends AbstractLanguage{
public static final String KEY = "rpg";
private Settings settings;
public RpgLanguage(Settings settings) {
super(KEY, "Rpg");
this.settings = settings;
}
public String[] getFileSuffixes() {
String[] suffixes = settings.getStringArray("");
if (suffixes == null || suffixes.length == 0) {
suffixes = StringUtils.split(".RPG", ",");
}
return suffixes;
}
}
After, I have created my RpgRulesDefinition class that implements RulesDefinition. In this class, I create a new repository for the language RPG and I want to add a rule in this repository (empty rules). The code is like below :
public static final String REPOSITORY_KEY = "rpg_repository_mkoza";
public void define(Context context) {
NewRepository repo = context.createRepository(REPOSITORY_KEY, "rpg");
repo.setName("Mkoza Analyser rules RPG");
// We could use a XML or JSON file to load all rule metadata, but
// we prefer use annotations in order to have all information in a single place
RulesDefinitionAnnotationLoader annotationLoader = new RulesDefinitionAnnotationLoader();
annotationLoader.load(repo, RpgFileCheckRegistrar.checkClasses());
repo.done();
}
My class RpgFileCheckRegistrar that call my Rules :
/**
* Register the classes that will be used to instantiate checks during analysis.
*/
public void register(RegistrarContext registrarContext) {
// Call to registerClassesForRepository to associate the classes with the correct repository key
registrarContext.registerClassesForRepository(RpgRulesDefinition.REPOSITORY_KEY, Arrays.asList(checkClasses()), Arrays.asList(testCheckClasses()));
}
/**
* Lists all the checks provided by the plugin
*/
public static Class<? extends JavaCheck>[] checkClasses() {
return new Class[] {
RulesExampleCheck.class
};
}
/**
* Lists all the test checks provided by the plugin
*/
public static Class<? extends JavaCheck>[] testCheckClasses() {
return new Class[] {};
}
My Rule class (still empty):
#Rule(
key = "Rule1",
name = "Rule that make nothing",
priority = Priority.MAJOR,
tags = {"example"}
)
public class RulesExampleCheck extends BaseTreeVisitor{
/**
* Right in java code your rule
*/
}
And the class SonarPlugin that call all these extensions :
public final class RpgSonarPlugin extends SonarPlugin
{
// This is where you're going to declare all your Sonar extensions
public List getExtensions() {
return Arrays.asList(
RpgLanguage.class,
RpgRulesDefinition.class,
RpgFileCheckRegistrar.class
);
}
}
The problem when I want to start the server sonar, I obtain this error stack :
Exception sending context initialized event to listener instance of class org.sonar.server.platform.PlatformServletContextListener
java.lang.IllegalStateException: One of HTML description or Markdown description must be defined for rule [repository=rpg_repository_mkoza, key=Rule1]
I try different things but I don't understand why there are these error.
Of course I want that my repository "rpg_repository_mkoza" is display in the RPG's repository in SonarQube with the Rules : RulesExampleCheck.
My sonar-plugin-version is the 3.7.1
I find my problem. There are need to add the field 'description' in #Rule.
For example :
#Rule(
key = "Rule1",
name = "RuleExampleCheck",
description = "This rule do nothing",
priority = Priority.INFO,
tags = {"try"}
)

Pointcut for method with call of the specific method inside

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.

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.

Ninject Conventions with Ninject Factory Extension To Bind Multiple Types To One Interface

I'm trying to expand on the scenario asked in the SO question titled Ninject Factory Extension Bind Multiple Concrete Types To One Interface by using Ninject Conventions for convention-based binding of the ICar implementations.
I'm working off the accepted answer authored by Akim and his Gist outlining the full example.
The difference is that I've replaced the explicit ICar bindings with convention-based bindings (or an attempt at it, at least ;)
public class CarModule : NinjectModule
{
public override void Load()
{
Bind<ICarFactory>()
.ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());
// my unsuccessful binding
Kernel.Bind(scanner => scanner
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<ICar>()
.BindAllInterfaces());
//Bind<ICar>()
// .To<Mercedes>()
// .Named("Mercedes");
//Bind<ICar>()
// .To<Ferrari>()
// .Named("Ferrari");
}
}
When I attempt to instantiate the car variable in the test, I get an ActivationException:
Ninject.ActivationException was unhandled by user code
Message=Error activating ICar
No matching bindings are available, and the type is not self-bindable.
Activation path:
1) Request for ICar
Suggestions:
1) Ensure that you have defined a binding for ICar.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
Source=Ninject
StackTrace:
at Ninject.KernelBase.Resolve(IRequest request) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 362
at Ninject.ResolutionExtensions.GetResolutionIterator(IResolutionRoot root, Type service, Func`2 constraint, IEnumerable`1 parameters, Boolean isOptional, Boolean isUnique) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 263
at Ninject.ResolutionExtensions.Get(IResolutionRoot root, Type service, String name, IParameter[] parameters) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 164
at Ninject.Extensions.Factory.Factory.InstanceResolver.Get(Type type, String name, Func`2 constraint, ConstructorArgument[] constructorArguments, Boolean fallback) in c:\Projects\Ninject\ninject.extensions.factory\src\Ninject.Extensions.Factory\Factory\InstanceResolver.cs:line 75
at Ninject.Extensions.Factory.StandardInstanceProvider.GetInstance(IInstanceResolver instanceResolver, MethodInfo methodInfo, Object[] arguments) in c:\Projects\Ninject\ninject.extensions.factory\src\Ninject.Extensions.Factory\Factory\StandardInstanceProvider.cs:line 78
at Ninject.Extensions.Factory.FactoryInterceptor.Intercept(IInvocation invocation) in c:\Projects\Ninject\ninject.extensions.factory\src\Ninject.Extensions.Factory\Factory\FactoryInterceptor.cs:line 57
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ICarFactoryProxy.CreateCar(String carType)
at Ninject.Extensions.Conventions.Tests.NinjectFactoryTests.A_Car_Factory_Creates_A_Car_Whose_Type_Name_Equals_Factory_Method_String_Argument() in C:\Programming\Ninject.Extensions.Conventions.Tests\NinjectFactoryTests.cs:line 33
InnerException:
How can I get this test to pass?
[Fact]
public void A_Car_Factory_Creates_A_Car_Whose_Type_Name_Equals_Factory_Method_String_Argument()
{
// auto-module loading is picking up my CarModule - otherwise, use:
// using (StandardKernel kernel = new StandardKernel(new CarModule()))
using (StandardKernel kernel = new StandardKernel())
{
// arrange
string carTypeArgument = "Mercedes";
ICarFactory factory = kernel.Get<ICarFactory>();
// act
var car = factory.CreateCar(carTypeArgument);
// assert
Assert.Equal(carTypeArgument, car.GetType().Name);
}
}
Here's the rest of the code, as condensed as possible, so that you don't have to refer to the original question
public interface ICarFactory { ICar CreateCar(string carType); }
public interface ICar { void Drive(); void Stop(); }
public class Mercedes : ICar {
public void Drive() { /* mercedes drives */ }
public void Stop() { /* mercedes stops */ }
}
public class Ferrari : ICar {
public void Drive() { /* ferrari drives */ }
public void Stop() { /* ferrari stops */ }
}
public class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
protected override string GetName(MethodInfo methodInfo, object[] arguments)
{
return (string) arguments[0];
}
protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
{
return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
}
Looks like, you have to define binding differently and provide your custom implementation of IBindingGenerator for this case
Binding
All implementation of ICar will have custom binding
Kernel.Bind(scanner => scanner
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<ICar>()
.BindWith(new BaseTypeBindingGenerator<ICar>()));
Custom IBindingGenerator implementation
Searching for all implementations of interface and bind them by type name
public class BaseTypeBindingGenerator<InterfaceType> : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (type != null && !type.IsAbstract && type.IsClass && typeof(InterfaceType).IsAssignableFrom(type))
{
yield return bindingRoot.Bind(typeof(InterfaceType))
.To(type)
.Named(type.Name) as IBindingWhenInNamedWithOrOnSyntax<object>;
}
}
ps: here is a full sample

Get and Set attribute values of a class using aspectJ

I am using aspectj to add some field to a existing class and annotate it also.
I am using load time weaving .
Example :- I have a Class customer in which i am adding 3 string attributes. But my issues is that I have to set some values and get it also before my business call.
I am trying the below approach.
In my aj file i have added the below, my problem is in the Around pointcut , how do i get the attribute and set the attribute.
public String net.customers.PersonCustomer.getOfflineRiskCategory() {
return OfflineRiskCategory;
}
public void net.customers.PersonCustomer.setOfflineRiskCategory(String offlineRiskCategory) {
OfflineRiskCategory = offlineRiskCategory;
}
public String net.customers.PersonCustomer.getOnlineRiskCategory() {
return OnlineRiskCategory;
}
public void net.customers.PersonCustomer.setOnlineRiskCategory(String onlineRiskCategory) {
OnlineRiskCategory = onlineRiskCategory;
}
public String net.customers.PersonCustomer.getPersonCommercialStatus() {
return PersonCommercialStatus;
}
public void net.customers.PersonCustomer.setPersonCommercialStatus(String personCommercialStatus) {
PersonCommercialStatus = personCommercialStatus;
}
#Around("execution(* net.xxx.xxx.xxx.DataMigration.populateMap(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
Object arguments[] = joinPoint.getArgs();
if (arguments != null) {
HashMap<String, String> hMap = (HashMap) arguments[0];
PersonCustomer cus = (PersonCustomer) arguments[1];
return joinPoint.proceed();
}
If anyone has ideas please let me know.
regards,
FT
First suggestion, I would avoid mixing code-style aspectj with annotation-style. Ie- instead of #Around, use around.
Second, instead of getting the arguments from the joinPoint, you should bind them in the pointcut:
Object around(Map map, PersonCustomer cust) :
execution(* net.xxx.xxx.xxx.DataMigration.populateMap(Map, PersonCustomer) && args(map, cust) {
...
return proceed(map, cust);
}
Now, to answer your question: you also need to use intertype declarations to add new fields to your class, so do something like this:
private String net.customers.PersonCustomer.OfflineRiskCategory;
private String net.customers.PersonCustomer.OnlineRiskCategory;
private String net.customers.PersonCustomer.PersonCommercialStatus;
Note that the private keyword here means private to the aspect, not to the class that you declare it on.