Monday, November 9, 2009

Working Code: Running scripts from GroovyScriptCommand

Working off of the examples of the existing CommandFactories and Commands in the code, I wrote the GroovyScriptCommandFactory and the GroovyScriptCommand as a wrapper for all script commands. There are some assumptions made in the existing code that instances of Commands will be known at compile time so that information about them, such as annotations on the class, can be used for help output and command names. I'm not crazy about this as it makes doing dynamic commands much harder. I would have preferred to have a more standard abstract method or something that can be called so that I could, for example, return the description of the script from the script itself which is known at runtime when the method would be called. As it is, there are helper classes which reflect on the Command subclass and output the description from the annotation.

I think my two options here are
  1. Go with a single GroovyScriptCommand that has a lame description defined in the annotation like "To get help for this script, run it with 'help' as the only argument"
  2. Do some crazy runtime class modification to add annotations to the subclass when the script name is known and load the description from the script if it is available and return some standard "no help" message if the script does not implement a description. I'm not yet sure how the script would do this. That is left as an exercise for future me.
Right now I'm going with #1 as its quick and easy. We'll see how hard #2 is later.

I'm actually pretty happy with the GroovyScriptCommandFactory. This is the subclass of CommandFactory that is responsible for creating the instances of Command based on a string name. This is pretty easy as the string name of the command will be the name of the groovy command without the .groovy at the end. I decided to return a Command object even if the script requested doesn't exist so that the exception can be thrown when the Command.execute() method is called. Since CommandFactory.createCommand(String) does not throw exceptions I could only return null which isn't hugely helpful.

Unit tests work and I can read variables set in the script binding and write new ones which can be read by the unit tests. There's still a little more work to have the GroovyScriptCommandFactory get created on startup and be asked to create Commands. Right now there is only one hard coded CommandFactory called and it is configured by a property file. I'm not sure how flexible this needs to be or if I can just change it to create the original CommandFactory and the groovy one and call one or the other first. My gut reaction is to have the scripts override the built in commands as that's how bash works but I could easily see it going the other way as overwriting builtin commands is crazy making. Its like monkey patching in dynamic languages. Not for the faint of heart.

No comments:

Post a Comment