AspectJ staticinitalization - aspectj

i'm successfully intercepting the static initialization of classes with #MyAnnotation with this code:
public aspect SomeAspect {
pointcut printClassName() : staticinitialization(#MyAnnotation *);
after() : printClassName() {
System.out.println(getClass().getName());
}
}
The question is: how do i get the name of the loaded class? In the code above what's printed is the name of the aspect class, not the name of the loaded class.
Thanks,
Teo

You should use thisJoinPoint to get these type of information. This code does the trick.
after(): printClassName(){
System.out.println(thisJoinPoint.getSignature().getDeclaringTypeName());
}

Related

How to write C# implementation for a Q# operation with intrinsic body?

I have created a library in C# to be used in Q# programs. The library has two scripts, a C# class library called "Class1.cs" and a matching Q# script called "Util.qs", I share the code snippet of each here:
Class1.cs:
using System;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace MyLibrary {
class Class1 : QuantumSimulator {
static void Method_1 (string str) { ... }
.
.
.
}
}
Util.qs:
namespace MyLibrary {
operation Op_1 (str : String) : Unit { body intrinsic; }
}
There is another Q# program in a different namespace that uses the namespace "MyLibrary" so after adding reference, in this Q# program I have:
namespace QSharp
{
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open MyLibrary;
operation TestMyLibrary() : Unit {
Op_1("some string");
}
}
When I execute "dotnet run" in the terminal I receive this message:
Unhandled Exception: System.AggregateException: One or more errors
occurred. (Cannot create an instance of MyLibrary.Op_1 because it is
an abstract class.) ---> System.MemberAccessException: Cannot create
an instance of MyLibrary.Op_1 because it is an abstract class.
How can I fix it?
Thanks.
UPDATE:
Following Mariia' answer and also checking Quantum.Kata.Utils, I changed my code as following:
So, I changed Class1 script to:
using System;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace MyLibrary {
class Class1 : QuantumSimulator {
private string classString = "";
public Class1() { }
public class Op_1_Impl : Op_1{
string cl_1;
public Op_1_Impl (Class1 c) : base (c) {
cl_1 = c.classString;
}
public override Func<string, QVoid> Body => (__in) => {
return cl1;
};
}
}
Now the error messages are:
error CS0029: Cannot implicitly convert type 'string' to 'Microsoft.Quantum.Simulation.Core.QVoid'
error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types
in the block are not implicitly convertible to the delegate return type
Having checked Quantum.Kata.Utils, I realised I need to create a field and a constructor for Class1 which is a base class and also I should override Func<string, QVoid> as the Op_1 parameter is string type. But I am not sure if each of these steps individually is done properly?
Second Update:
I have changed the previous c# code in first update to the following one:
using System;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace MyLibrary {
class Class1 : QuantumSimulator {
public Class1() { }
public class Op_1_Impl : Op_1{
Class1 cl_1;
public Op_1_Impl (Class1 c) : base (c) {
cl_1 = c;
}
public override Func<string, QVoid> Body => (__in) => {
return QVoid.Instance;
};
}
}
Now the error message is the same as the very first one:
Unhandled Exception: System.AggregateException: One or more errors
occurred. (Cannot create an instance of MyLibrary.Op_1 because it is
an abstract class.) ---> System.MemberAccessException: Cannot create
an instance of MyLibrary.Op_1 because it is an abstract class.
And also in this new code shouldn't the constructor public Class1() { } have a parameter? if so what datatype?
In your code, there is nothing connecting the Q# operation Op_1 and the C# code that you intend to implement it in Method_1.
Q# operations are compiled into classes. To define a C# implementation for a Q# operation with the intrinsic body, you have to define a class that implements the abstract class into which your Q# operation gets compiled; so you would have something like public class Op_1_Impl : Op_1.
Getting all the piping right can be a bit tricky (it's a hack, after all!) I would recommend looking at the operation GetOracleCallsCount and its C# implementation to see the exact pieces that have to be in place for it to work.
For the updated question, the signature of your method says that it takes string as an input and returns nothing (QVoid), but the implementation tries to return a string cl_1, so you get a Cannot implicitly convert type 'string' to 'Microsoft.Quantum.Simulation.Core.QVoid'.
To provide a custom C# emulation for your Op_1 Q# operation, you'll need to replace your Class1.cs with something like this:
using System;
using Microsoft.Quantum.Simulation.Core;
namespace MyLibrary
{
public partial class Op_1
{
public class Native : Op_1
{
public Native(IOperationFactory m) : base(m) { }
public override Func<String, QVoid> Body => (str) =>
{
// put your implementation here.
Console.WriteLine(str);
return QVoid.Instance;
};
}
}
}
You can then run the Test1Library using the QuantumSimulator.
That being said, as Mariia said, this is kind of hacky, undocumented functionality that might change in the future, may I ask why you need this?

Spring AOP : Interface method with Parameter annotation captured, but annotation is not present

I'm using Spring AOP to intercept a method execution.
I have an interface that looks like the following:
public interface MyAwesomeService {
public Response doThings(int id, #AwesomeAnnotation SomeClass instance);
}
Here is the implementation of the interface:
public class MyAwesomeServiceImpl implements MyAwesomeService {
public Response doThings(int id, SomeClass instance) {
// do something.
}
}
Now i would like any method which has a parameter annotated with #AwesomeAnnotation should be captured by Spring AOP.
So I wrote the following aspect which works.
#Aspect
#Component
public class MyAwesomeAspect {
#Around("myPointcut()")
public Object doAwesomeStuff(final ProceedingJoinPoint proceedingJoinPoint) {
final MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
// annotationMatrix is empty.
}
#Pointcut("execution(public * *(.., #package.AwesomeAnnotation (package.SomeClass), ..))")
public void myPointcut() {}
}
However when I try to find the parameter annotations I don't get any annotations back. As mentioned above, the annotationMatrix is empty.
So here are my questions:
Why is the annotationMatrix empty? Probably because parameter annotations are not inherited from an interface.
Why I'm able to capture the method execution. Since Spring AOP is able match the pointcut, Spring somehow is able to see the method's parameter annotations but when I try to see that using methodSignature.getMethod().getParameterAnnotations() it doesn't work.
I also faced this issue with one of my parameter annotations. I was able to fix the same by making sure that the parameter annotation definition had RetentionPolicy as RUNTIME and Target as PARAMETER
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface Param {
public String name();
}
The answers to your questions:
Parameter annotations are not inherited from interfaces to implementing methods. In fact, annotations are almost never inherited, only from class (not interface!) to subclass if the annotation type itself is annotated by #Inherited, see JDK API documentation.
Update: Because I have answered this question several times before, I have just documented the problem and also a workaround in Emulate annotation inheritance for interfaces and methods with AspectJ.
Because during compile or weave time AspectJ can match your pointcut against the interface method and thus sees the annotation.
You can fix the situation by adding the annotation to the parameter in your interface implementation, e.g. like this:
#Override
public Response doThings(int id, #AwesomeAnnotation SomeClass instance) {
// ...
}
Then with an aspect like this...
#Aspect
#Component
public class MyAwesomeAspect {
#Pointcut("execution(public * *..MyAwesomeService.*(*, #*..AwesomeAnnotation (*), ..)) && args(*, instance, ..)")
static void myPointcut(SomeClass instance) {}
#Around("myPointcut(instance)")
public Object doAwesomeStuff(Object instance, ProceedingJoinPoint proceedingJoinPoint) {
System.out.println(proceedingJoinPoint);
System.out.println(" instance = " + instance);
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
for (Annotation[] annotations : annotationMatrix) {
for (Annotation annotation : annotations) {
System.out.println(" annotation = " + annotation);
}
}
return proceedingJoinPoint.proceed();
}
}
... you get a console log similar to this:
execution(Response de.scrum_master.app.MyAwesomeServiceImpl.doThings(int, SomeClass))
instance = de.scrum_master.app.SomeClass#23fc625e
annotation = #de.scrum_master.app.AwesomeAnnotation()

Cast class to base interface via reflection cause exception

I'm loading a .NET assembly dinamically via reflection and I'm getting all the classes that it contains (at the moment one). After this, I'm trying to cast the class to an interface that I'm 100% sure the class implements but I receive this exception: Unable to cast object of type System.RuntimeType to the type MyInterface
MyDLL.dll
public interface MyInterface
{
void MyMethod();
}
MyOtherDLL.dll
public class MyClass : MyInterface
{
public void MyMethod()
{
...
}
}
public class MyLoader
{
Assembly myAssembly = Assembly.LoadFile("MyDLL.dll");
IEnumerable<Type> types = extension.GetTypes().Where(x => x.IsClass);
foreach (Type type in types)
{
((MyInterface)type).MyMethod();
}
}
I have stripped out all the code that is not necessary. This is basically what I do. I saw in this question that Andi answered with a problem that seems the same mine but I cannot anyway fix it.
You are trying to cast a .NET framework object of type Type to an interface that you created. The Type object does not implement your interface, so it can't be cast. You should first create a specific instance of your object, such as through using an Activator like this:
// this goes inside your for loop
MyInterface myInterface = (MyInterface)Activator.CreateInstance(type, false);
myInterface.MyMethod();
The CreateInstance method has other overloades that may fit your needs.

How to get the caller method information from Around advise

ThisJoinPoint can only get the current method information, anyway to get the caller method information?
You can try the special variable thisEnclosingJoinPointStaticPart which holds the static part of the enclosing JoinPoint.
Mentioned here (example) and here (docs)
Or if using annotation-based AspectJ, pass following to the advice method's parameters, e.g.:
#Before("call( /* your pointcut definition */ )")
public void myCall(JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart)
{
// ...
}
Mentioned here
#Aspect
public class LoggingAspect {
#Before(value = "execution(public * findAll())")
public void beforeAdvice(JoinPoint pp){
System.out.println("before advice called ....get calling method Signature"+pp.getSignature());
System.out.println("before advice called ....get calling method name"+pp.getSignature().getName());
}
}

aspectj - how to find a method of an annotated class is calling another method of same class. i.e. nested calls

I have an annotation #AppManaged which is used to signify classes that need to have certain behavior woven in. One behavior woven in is converting method calls into concurrent GPars(a groovy parallel library) calls instead.
However I do not want nested method calls on the same class to be advised.
So...
#AppManaged
class someclass
{
public void method1(){
method2(); **// should not be advised**
}
public void method2(){
}
}
But if the method call is from on AppManaged class to another, then it is supposed to be advised, hence something like !cflowbelow(#within(AppManaged)) does not help.
#AppManaged
class Someotherclass
{
private someclass s;
public void method3(){
s.method2();**// Should be advised.**
}
}
Basically I am looking for a pointcut which will match only nested calls within the same object instance and prevent them from being advised.
Any help would be highly appreciated.
Thanks and Regards
Abraham Menacherry.
How about:
pointcut appManagedExecution(Object appManaged) : execution(* (#AppManaged *).*(..)) && this(appManaged);
pointcut appManagedCall(Object called) : call(* (#AppManaged *).*(..)) && target(called);
pointcut routed(Object appManaged, Object called) : appManagedCall(called) && cflowbelow(appManagedExecution(appManaged)) && if(called != appManaged);