Can reflection bind a class to a new name? - java

I am trying to let users of my program rename classes and methods in the class. The new names can be read in and configured at run time and they will call these classes and methods in a scripting language using Java Script Engine. I need a way to bind their new names to the real names of the classes and methods. I have been looking at Reflection but I do not think this can provide me with the capability I need, or is this even possible?
Ex:
public class RealName {
public void printHello() {
System.out.println("Hello");
}
}
Then in maybe Paython say
obj = new NewName()
obj.hello()
Tell me if this is impossible please!

You can not change the method names, but you can bind an instance of an object to a given name and inject that into the context of the scripting language.
This would only work for that instance of the class, not for instantiating new instances.
If you really want this you may be able to generate sub classes with the new name and method names in the target scripting language and inject them into to the context to get the effect you are looking for.
Having said all that I can't really come up with a good reason to do any of this.

To answer my question from what I've found no you cannot use reflection to bind a class to a new name. In fact I found no easy way to do dynamic renaming.
What I did to overcome this was to write code from a string to a file, save that file with extension .java, compile that file, then use it with reflection or better yet use it inside a script using the Java ScriptEngine API (that way you can avoid the ugly reflection code and actually have everything dynamic and on the fly).
Here's a starting point for creating the file,
Dynamic in-memory compilation
And here's something for scripting Java,
Scripting for Java

Related

Can I convert a string to a java code [duplicate]

Similar to dynamic SQL, wherein a String is executed as an SQL at runtime, can we have Java code run dynamically? Like I return a String which is a Java code and then I execute at runtime. Is this possible?
For real Java code, this is possible using the JavaCompiler interface. However, it's very inconvenient to use since it's just an interface to a real Java compiler that expects to compile entire class definitions found in files.
The easiest way to execute code supplied at runtime would be to use the Rhino JavaScript engine.
Both of these options have been only in Java 6, though I believe the scripting interface existed before, so you could use Rhino in an earlier JRE if you download and add it to the classpath.
Javassist
You would need to use a bytecode manipulation library such as Javassist (Wikipedia), in order to run an arbitrary string that is provided at runtime. Javassist allows you to create a CtClass based on a string representing source code; and can then turn this into compiled Class object via a particular classloader, so that the class is then available to your application. Other libraries would need to do something similar to these two steps in order to achieve the same thing.
So it is possible, but it's very heavyweight and is likely to make your application very hard to reason about. If at all possible, consider designing a very flexible class statically, and having it accept parameters that control its behaviour.
If you want to do more than invoke an existing method dynamically, you may need to compile your String into bytecode. An easy way to do this is to include the Eclipse/JDT compiler jar in your classpath, and then you can use that to compile your String into a Class, which can then be loaded.
This type of dynamic code generation and execution is used to convert JSP files into Servlets and is used in other packages such as JasperReports to turn a report specification into a Class that is then invoked.
Remember that just as with SQL you must be careful to prevent code injection security problems if any of the String contains user-specified data.
You also may want to look at Java 6 scripting support:
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.htm
Here is a version of hello world that creates array of strings and prints a first one:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
}
}
Yes it is possible. Look at the Java Compiler API. Have a look here:
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html
Have a look at Beanshell. It provides an interpreter with java like syntax.

Extracting class usage from within Java methods using ctags

I would like to know if it is possible to use ctags to extract class usage from within Java methods. So far, I was able to only use it to get a listing of methods and instance variables but not which classes are utilized within methods.
E.g.
...
public void doSomething(MyClass myClassInst) {
int someVar = myClassInst.getSomeVar();
System.out.println("Some var is " + someVar);
}
...
Right now all I get is a recognition of the method declaration. But I would like to extract that doSomething is also utilizing the classes MyClass and System but not just to parse the text but also know the full class address including the package (java.lang.System and com.mypackage.MyClass).
In order to be able to extract this kind of metadata, ctags would need to have access to the compiler's abstract syntax tree and I am not sure if it does that or it simply does text parsing of the source code.
Is there a way to accomplish what I am trying to do using ctags or does it eclipse the scope of its functionality?
You can use asm or BCEL to achieve this.

Include automatically generated methods in a java class

I have a question which I am not sure can be answered.
I have a php script on a server that automatically generates a java method based on table contents in a MySQL Database. The script creates a .java file in which this method is saved.
I then download this method and copy and paste the method into my main java class. I think this is an unnecessary step. Is there a way to include the method in the java class rather than copying and pasting.
I am looking to write a reference to the method.java file at the point in the java class where the method should be copied and pasted.
Something like:
public class ShowAlert {
public void showAlert(String toast) throws IOException {
System.out.println("alert = "+externalMethod());
}
include(externalMethod.java);
}
and then externalMethod.java has
public String externalMethod(){
return "hello world";
}
I am not sure if this is possible but it would be great if it was.
There is no "include file" facility in Java. I suggest that you generate this instead:
public class GeneratedClass {
public static String externalMethod(){
return "hello world";
}
}
and call it like this:
GeneratedClass.externalMethod();
That way, the handwritten file and the generated file can be completely separate.
You should really consider to use something like Java ScriptEngine (described in JSR 223). Examples can be found here.
There are also LUA integrations for Java.
You would ideally keep generated code and manually written code in separate files. In that way you wont have to do what you are doing. Use Aasmund's suggestion. That's the right way to go. You might have to restructure your code to allow this, but better now than later.
I would ask you to go the extra mile and use interfaces. Your generated code should implement an interface and your manual code should reference everything using the interface alone. You could have a Factory that returns the instance.
This will allow you to increase your decoupling of manual code and the generated code. I would think that would you are doing is using the DAO (data access object) pattern to a certain extent. The DAO pattern works best, if you keep the generated code separate and access it using interfaces. Using interfaces will allow you to change the implementation of the DAO to something else at runtime - such as to run unit tests.
You could use a PHP template engine like Smarty to create your complete java class. Your main class will be your template with a placeholder for the generated method.

Java/Ruby: is there a way to do .constantize or Object.send() in Java?

In Ruby, you can do "var1".constantize to get the actual variable var1.
Ruby also has Model.Send("method name, parameters can be here, etc"), and it would be the same as actually calling that method.
What I want to do.. is... kinda tricky... I want the string "var1 == var2" to be converted to actual variables in my java app, then evaluated.
Is there a way to do this?
Have you considered using JRuby?
As to your questions:
There is no peer to constantize that will allow for an eval like syntax where you can pass in a String and convert it to code in Java. You can do things like Class.forName to load a particular class from a String, but it doesn't sound that is what you are looking for.
You can use the Java reflection API to dynamically invoke methods on a class Check out Jakarta Commons BeanUtils for some utility methods that may help.
In Java, similar behaviour is achieved through the Reflection API. However, since Java is a compiled language, local variables' (within methods, constructors, parameters, etc) information is erased on compilation.
However you still have complete access to class names, hierarchies, methods and fields (class variables).
A good starting point is the Reflection API tutorial or the getClass() method of Object.
In Java if you want a dynamic lookup of variables, you would typically place them in a Map and lookup use the keys of that Map.
Can you explain what you are trying to do in more detail, I suspect what you are trying to do can be done simply a different way in Java.

Dynamic code execution

Similar to dynamic SQL, wherein a String is executed as an SQL at runtime, can we have Java code run dynamically? Like I return a String which is a Java code and then I execute at runtime. Is this possible?
For real Java code, this is possible using the JavaCompiler interface. However, it's very inconvenient to use since it's just an interface to a real Java compiler that expects to compile entire class definitions found in files.
The easiest way to execute code supplied at runtime would be to use the Rhino JavaScript engine.
Both of these options have been only in Java 6, though I believe the scripting interface existed before, so you could use Rhino in an earlier JRE if you download and add it to the classpath.
Javassist
You would need to use a bytecode manipulation library such as Javassist (Wikipedia), in order to run an arbitrary string that is provided at runtime. Javassist allows you to create a CtClass based on a string representing source code; and can then turn this into compiled Class object via a particular classloader, so that the class is then available to your application. Other libraries would need to do something similar to these two steps in order to achieve the same thing.
So it is possible, but it's very heavyweight and is likely to make your application very hard to reason about. If at all possible, consider designing a very flexible class statically, and having it accept parameters that control its behaviour.
If you want to do more than invoke an existing method dynamically, you may need to compile your String into bytecode. An easy way to do this is to include the Eclipse/JDT compiler jar in your classpath, and then you can use that to compile your String into a Class, which can then be loaded.
This type of dynamic code generation and execution is used to convert JSP files into Servlets and is used in other packages such as JasperReports to turn a report specification into a Class that is then invoked.
Remember that just as with SQL you must be careful to prevent code injection security problems if any of the String contains user-specified data.
You also may want to look at Java 6 scripting support:
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.htm
Here is a version of hello world that creates array of strings and prints a first one:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
}
}
Yes it is possible. Look at the Java Compiler API. Have a look here:
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html
Have a look at Beanshell. It provides an interpreter with java like syntax.

Categories

Resources