Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Build a Reflection-based Interpreter in Java : Page 4

Java's support of reflection enables you to create an interpreter that executes commands interactively. This article demonstrates how to build a reflection-based system that allows simple scripting of Java programs without having to install a special-purpose scripting language. It also provides a downloadable sample program.

Method.invoke actually calls the method. This method takes two arguments: the object instance and the arguments. Since you are calling a static method, you don't have an object instance. So use null as the instance:

try { Object retval = method.invoke( null, args ); } catch( IllegalAccessException iae ) { throw new CommandLineException( "Not allowed to call method "+ methodName+" in "+className ); } catch( InvocationTargetException ite ) { throw (CommandLineException) new CommandLineException( "Exception while executing command" ) .initCause( ite ); }

This code throws a couple of exceptions. IllegalAccessException is thrown if you don't have privileges to call the method, such as when it's a private method. InvocationTargetException is thrown if the method itself throws an exception. The actual method exception is wrapped in an instance of InvocationTargetException, and you wrap this in a CommandLineException and then throw it again.

Returning a Value
As mentioned earlier, any return value is printed to the CommandLine's output stream. When you called Method.invoke, you got an Object as a return value. You can simply convert this to a String, and print that string to the output stream. CommandLine.execute converts the object to a string, which is printed to the output stream:

String result = execute( line ); out.write( result );

Write Scripts
Since you have a scripting language, why not write scripts? You can supply the following script to the interpreter (under Unix or a Windows command prompt):

TinyChatServer startServer 5000 TinyChatServer startServer 5555 Calculator add 10.0 20.0 Calculator subtract 10.0 20.0 Calculator multiply 10.0 20.0 Calculator divide 10.0 20.0

When you supply this file as the input to the Test program, it runs each of the commands in sequence. The following is the output:

% java Test < test.input.txt $ Server started on port 5000 $ Server started on port 5555 $ 30.0 $ -10.0 $ 200.0 $ 0.5 $ Command line exiting. Listening on ServerSocket[addr=,port=0,localport=5555] Listening on ServerSocket[addr=,port=0,localport=5000]

The Power of Reflection
The Reflection API is powerful enough that one actually could write a full-fledged Java interpreter--and in fact developers have already done it (see the BeanShell site). Obviously, the program provided here is suited for running more simple commands. However, you could easily use the solution described in this article to add administrative commands to an existing server. Simply connect a CommandLine to a network port and you'd enable users to connect to a running server and issue commands to it.

Greg Travis is a freelance Java programmer and technology writer living in New York City. After spending three years in the world of high-end PC games, he joined EarthWeb, where he developed new technologies with the then new Java programming language. Since 1997, he has been a consultant in a variety of Web technologies. He can be reached at mito@panix.com.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.