Make proxy on Kotlin class from a Java library using ASM - java

I have a Java library that creates a proxy using ASM.
At one point, user sends a Kotlin class to it. I can detect it is a Kotlin class from Java, but I don't know how can I make a proxy from it? Everything what I read from such class is meaningless.
The scenario is the following
user sends a Kotlin class
I make a proxy
finally, I make an instance of such class
what would be the best way to do so?
EDIT
I just realized that one of the reasons why I can't override Kotlin functions is because they are generated as final methods in the bytecode. Is there a way to tell Kotlin not to do so?

The issue I had was that generated classes and methods are final. The ASM code I am using was not processing final methods as they can not be overwritten.
The solution is to mark classes and functions in Kotlin as open. You can do this manually or using all-open plugin.
Here is a page that explains the issue: https://blog.frankel.ch/open-your-classes-and-methods-in-kotlin/

Related

Is it possible to override files from android sdk?

For example i want customize BluetoothGatt class. Is it possible to create android.bluetooth package and put own version of this class?
BluetoothGatt uses android interface files shown in here. Can i access these files and use it in own version of BluetoothGatt?
Yes as long as you match the package and class name, when you reference it in your code, you will be able invoke your custom behaviour / modified contract
Android classes are simply Java. You can modify the support SDK, as it is simply a Java file. However, this is only applying to your app, or it would be possible for apps to change the entire SDK, which is defeating the point of sandboxing. If you want to extend the class, that is done just the same as in Java, as the class is just Java. However, this specific class is final, so you can't, at least not without hacks. However, the support library is usually a wrapper, so you may as well write your own. If the reason you want to do this is to access a private method, use reflection!
EDIT: To pedantically answer your question, you have already accessed said files, and copy-and-paste is always your friend!
Hope I helped!

How can I intercept a method call to a library class in Java or Android?

I have a library class that is a singleton and does NOT implement any interface (So I'm assuming I cannot use dynamic proxies). But, I need the same functionality as the dynamic proxy. I need to hijack the call, log some data and pass on the call to the library as is.
Is it possible to do this without having to use AspectJ or Spring AOP? (I'm not sure how to use these frameworks, but I will have to look into it if there is no other way).
You can provide your own implementation of the same class, with the same name and package, and try to put it into classpath first. The calling code with such classpath will pick the intercepting class first, and the intercepting class can call others classes of the actual package to provide its actual functionality.
Best would be to remove the overridden class from the library .jar with archive tool.
You could change the import statements in the classes that call f() so that they see a different class that implements f(). The implementation of that class would do the logging and call the real f().
Still requires some editing, but less than changing every call.
BTW: Depending on the size of the project, you may want to consider making wrappers to that "black box" anyway, if this type of requirement will be ongoing.
Like I started in my comment wrapper all the classes you implement from the external library. Then call the external library from your own classes this way you can log in the function(s) you want. If you use the same function name then you don't have to change what you call you only have to change your import(s). Most IDEs provide mass name replace so it shouldn't be too big of a burden it will be tedious however.

How to mock a static call on a class from a third-party library

I am wondering whether it is possible with PowerMock or any other library to mock out a static call in a class from a library. The class in that third-party library makes a call to one of the classes in the rt.jar and I want a return a custom implementation of that returned Type. I am trying to do this outside of test code.
Otherwise, I had to extend a few classes from that library and replace some implementation. Has someone done anything like this before?
Yes it is possible, e.g. using PowerMock.mockStatic() or PowerMock.mockStaticPartial() if you want to mock one method, only.
There is a quite good tutorial on the homepage of PowerMock.
I posted an example on SO.
[EDIT] IF you want to do such magic in production code, however, I would recommend NOT to use a Testing-Framework. Maybe Groovy can help you with that - it is possible with Groovy to manipulate classes (even JDK classes) at runtime, and it is (I think) a thinner layer on top of the JVM.
Generally speaking it's really bad idea to do such hardcore stubbing (it's not mocking what you describe). I'd go with building tiny abstraction over this library so that you can have full control on what you want to return. It is possible to use some features of PowerMock outside tests but this not piece of cake. Here you have rough description that can help if you really want: https://groups.google.com/d/msg/powermock/SMDMe-y6fLg/1HF0TsGOqTIJ
Anyway I would not recommend doing that.

Compile plugin code in Java without parent class body

I´m trying to add a plugin system to my app. I have an abstract class that plugins must extend. This class provide usuful methods so I really need it. The problem is that these plugins could be written by anyone so I suppouse that they'll need the abstract class code to be able to compile their code.
I don´t want to complicate the process of creating a plugin. Is there a way to compile the code without know the abstract class body (only its methods)?
Thanks in advance.
Is there a way to compile the code without know the abstract class body (only its methods)?
No. In order to to compile a class declared as
class A extends B
you'll have to have B in source format in the source path or in .class format on the class path.
(If knowing only the methods is sufficient for writing the plugin, it sounds more like you're after an interface than an abstract class.)
I don´t want to complicate the process of creating a plugin.
Providing the compiled .class file of B is completely uncomplicated and probably the best practice in this scenario.
Actually, having an API at hand through a .jar-file containing the relevant classes and interfaces is probably the standard.
To be clear:
Take the classes that are relevant for plugin-development, compile them, and put them in, say pluginapi.jar
Distribute the .jar and tell plugin developers that their plugins should compile, provided the pluginapi.jar
Ask the plugindevelopers to provide you with plugin.jar (not necessarily including pluginapi classes)
In your application, make sure that the plugin API classes are present, for instance by including them the class path.
Load the plugin classes.
You could ask your plugin authors to provide you some classes with some specified methods and invoke those using reflection. This would mean that they could write a plugin that can be compiled without access to any of your code.
But it would also severely limit their possibilities: How should the plugin interact with your system if they have no way of calling into it? Since the only sane way to provide that is to make some classes (or interfaces) accessible, you can just as well provide an interface (or abstract class) that they need to implement/extend.
You could put that interface (and all interfaces/classes visible to plugins) in a separate .jar file. This way they only need that jar file to compile a plugin.
You can just provide a jar file with all necessry java files. But remember, that once you publish the api, you should be very careful with changing it.
Alternatively you can go around by not forcing your users to extend a class or implement an interface but have them provide a function with a certain signature -- which then you can call via reflection. In this case they won't need anything from you, however, if they get the function wrong obviously you won't be able to call the plugin.
In these cases Java scripting can be very useful. Have your plugins written in Groovy and the codes can be easily (down)loaded and executed in your framework, something like this http://groovy.codehaus.org/Embedding+Groovy

How can I dynamically create a new .java file from a Java program?

I want to create a one .java from the Java program. When I run the program, automatically one Java file will created in my project, and also create some run time (dynamic) variable in that file. How can I do this?
I know for this I have to use a Reflection API like Class and Method, but what are the methods in Class and Method to do this?
You cannot create new classes or methods using the reflection APIs. They are not designed for this. (The Class and Method APIs are for performing operations on object instances in a dynamic fashion.)
If you want to create new code on the fly, there are two basic approaches to doing this:
Generate Java source code, write it to a file, use the Java compiler to compile it to a bytecode file, and then load the bytecodes. (There are standard APIs for running the Java compiler within the JVM of a running application.)
Use BCEL or equivalent to construct a bytecode file from scratch, and then load the bytecodes.
Both approaches are tricky and computationally expensive. The BCEL approach is particularly tricky because you need to understand a lot about the JVM to do the job.
Apparently you want to create a new class at Runtime and use it. You can sure create a .javafile, compile it and load it from a custom class loader but that's probably not the best/easiest thing to do. Here are a bunch of solutions:
First of all if you want to extend an interface, you can use the Proxy from the Java Reflection API.
It you want to extend a class rather than implements an interface or create a class out of the blue you need to use a library to create bytecode. You can find a bunch of them on http://www.java-opensource.com/open-source/bytecode-libraries.html. Among these libraries I like javassist mainly because it is the only library to my knowledge letting you enter Java code directly rather than bytecode.
A last solution should be to use a framework like Groovy or BSH to interpret pseudo-java code.
No, you can't generate new .java files using Reflection. You could perhaps create a new class, and use this class, in runtime, but you can't write that class out to file in the form of a .java source file.
Have a look at the JustAdd framework for instance. This framework solves this type of problems IIRC.
Java is a strongly typed language( As opposed to a weakly typed language). Simply put you need to have a Class (prototype) to create a instance of object. What you are trying to do is not natural in java (or any strongly typed language).
If you have to have this functionality in java, you need to use groovy. Groovy is a dynamic language that can run in Java JVM. You need to check Expandos in groovy.(ofcourse it still will not create a .java file).

Categories

Resources