Is it possible to just add method to class with Java Poet? - java

I am wondering if is it possible to add method to class without having to rewrite whole class again using Java Poet?
Thanks

JavaPoet emits source code, nothing else. It can't consume the source code of an existing class.
You could emit a method with it and insert it into the body of a class some other way, but that's as good as it gets.

Related

How to add methods the source code using ASTRewrite?

I was looking for some sample example code that could help me write full-fledged code for adding a method in another class using ASTRewrite.
P.S: It is not a problem of adding lines in a method that is already created. Instead, I wish to create a new method which doesn't exist in user's class and which has the capability of accepting parameters and has some code inside it.
If, generally, you are able to make changes using ASTRewrite then probably all you need is to obtain a ListRewrite for the body declarations of the declaring class, s.t. like:
astRewrite.getListRewrite(type, type.getBodyDeclarationsProperty())
the resulting ListRewrite has various insertX methods to suite your needs.
The method can be created beforehand using the factory methods from AST (i.e., for this you don't need to bother the rewriter for this).

Get caller class and method name

I am trying to get the caller class and method name inside a function in a Scala app. I am currently making use of the stack trace, but the performance has decreased. I am doing something like
stackTrace(CodeDepth).getClassName
stackTrace(CodeDepth).getMethodName
I have found the Java reflection to be a lot more faster, but i can only get the class name with
sun.reflect.Reflection.getCallerClass(CodeDepth).getName()
Is there a way to get the method name (and optionally the line number) via reflection? Maybe using Scala's reflection?
Thanks
Unfortunately, there is no non-expensive method to do this. There is a Java Enhancement Proposal to add a better alternative, but this doesn't help unless you can wait until Java 9 (and it isn't guaranteed to be included anyway).
On the other hand, is this really a hotspot in your code? This should only matter if it's called in a loop, and in this case you probably can call it once and cache the result.
For Scala you can just use the sourcecode library from https://github.com/lihaoyi/sourcecode and just do something like:
def log(foo: String)(implicit line: sourcecode.Line, file: sourcecode.File) = {
println(s"${file.value}:${line.value} $foo")
}
log("Foooooo") // sourcecode/shared/src/test/scala/sourcecode/Tests.scala:86 Fooooo

Is there a way to place a mark in bytecode?

What I am trying to do: I want to have a pre-compiled java byte-code file, and be able to place a "mark" in some places. Later I want to analyze this file using ASM and replace mark with some code. So, how can I implement this? Currently I am trying to do it, by inserting invocations of empty static method, but I still feeling like I am doing something wrong. Is there a better way to do this?
P.S. If more general, I want to have some precompiled class template, for example:
public class Main {
public static void Main(String... args){
System.out.println("Program starts!");
//I want to insert code here
System.out.println("Bye!");
}}
There is no Java statement without a predefined meaning, well, maybe with the exception of the empty statement ; which doesn’t create code that you can find in the byte code. There are annotations, but these can only be used to mark another code fragment, not to create a stand-alone statement within your code.
So you have to choose a statement to assign it the meaning of being a mark in your template code and your solution of using an invocation of a dedicated empty method is a perfect candidate for such a mark. Since it’s new meaning does not rely on the kind of statement but on the target method which resides in a class whose name is distinguishable from all other classes, there is no conflict between your mark and other statements.
But you should consider that the framing class code is rather trivial compared to the code you will generate when implementing a compiler for any non trivial language. In most cases, the logic of patching the generated code into an existing code will exceed the complexity of just generating a complete class file.
If you really have large pieces of unchanging code you should consider placing them into their own classes and generate classes using or extending them. This simplifies the code generation and avoids code duplication (the same reason why these techniques are used in manually written code).

Using jUnit to test a class / object which is not created yet

I am working on a program that will be a sort of game for beginner programmers. I intend to provide a field where the users can write code as required (method, class... ). When the user wants to submit the code, I will copy the content of the text field into a .java file, call the compiler to compile this class, and then I want to test whether the code works okay using jUnit.
Well, I know that jUnit is used for development purposes, but I think it could be very useful implementing it in this case as well.
Now the problem is that when I will need to compile my program, the class which will supposedly be tested (the user's code) is not going to be there. So I cannot just call
assertEquals( "Wrong sum", 6, Foo.sum( 4, 2));
because it will not know what Foo class is, since it will never be there at the time of compilatoin - before the user runs the application and starts coding.
I thought I could create a dummy class, just for the sake of compilation, but then when I will need the real thing, I won't be able to replace the file or write another file like Foo2.java, because the FooTest.java will only operate with object Foo....
I would really appreciate your suggestions guys!!! What can I do to deal with this situation?
Thanks :)
Two options:
Have the user implement an interface and use the interface in the JUnit
Use reflection to get the public method from the class and call it.
Reflection Version:
If you have an instance of the class you want to test (could be of type Object), use getClass to get the Class object. Then use getDeclaredMethods to get a list of the Methods. Iterate the Methods till you find the one you want to test (hopefully the only public method).

Listing the methods called from a java class?

I'm investigating ways to ensure a java class only calls a limited set of allowed methods from other classes. The usecase I have receives the class via the standard java serialization.
The approach I want to try is to simply list the methods it calls and only run the code if it passes a short whire list.
The question I have : how do I list the methods used in that class?
This is not a perfect solution but you coud use this if you can't find something better. You can use javap, if you're in Linux, run in the command line (or run a proccess using Runtime.exec()): javap -verbose /path/to/my/classfile.class | grep invoke and you'll have the binary signatures that the class "calls" from other classes. Yes, I know, it's not what you wanted but you could use it as a last resource.
If you need a more "javaish" solution, you could have a look at a java library called "asm": http://asm.ow2.org/
You could pass a dynamic proxy object to the caller, which inside checks the methods against your white list and throws exception when the call is not allowed.
Dynamic proxies basically allows you to insert piece of code between the caller's method invocation and the actual invocation of the called method.
I'd really think through though to if you really need this. Dynamic proxies are useful but they can also be very confusing and annoying to debug.

Categories