Skip to content

Instantly share code, notes, and snippets.

@rssh
Created March 12, 2012 21:00
Show Gist options
  • Save rssh/2024656 to your computer and use it in GitHub Desktop.
Save rssh/2024656 to your computer and use it in GitHub Desktop.
run command line program within play 2.0 environment
package commands
import scala.sys._
import play.api._
import java.io.File
/**
* Run command in play environment.
*
* Assume, that we have in play 'app' directory subdirectory 'commands'
* and in commands we have 'commands implementations' : scala objects or java
* classes with run(args:String*) method. Also Assume, that this implementation
* use play configuration, plugins api, etc ... - i. e. must run in play environment.
*
*This runner accept calls like CommandRunner.run("cmd",args), determinate implementation
*for "cmd" (i.e. object or class "commands.Cmd") and call run method of found implementation
*in play application environment (initializing one if needed)
*/
object CommandRunner
{
def insideApp[A](f: =>A):A =
{
if (Play.maybeApplication.isEmpty) {
val app = new Application(new File("."),this.getClass.getClassLoader, None, Mode.Test);
Play.start(app);
// play.stop will be called on jvm shutdown. Does not call one,
// immediatly after f, becouse we want to call command multiple times
// from sbt console.
try {
Runtime.getRuntime.addShutdownHook(ShutdownHookThread{ Play.stop() });
} catch {
case ex: IllegalArgumentException =>
// this hook was already registered (?) - may-be, skipping.
}
}
f;
}
def run(cmdname:String, args: String*):Unit =
{
val cmd = findCommandObject(cmdname);
try {
insideApp {
cmd.asInstanceOf[{ def run(args:String*):Unit }].run(args:_*)
}
} catch {
case ex: ClassCastException =>
throw new IllegalArgumentException(cmd.getClass.getName+" is not command: it does not define run");
}
}
def findCommandObject(cmdname:String):AnyRef =
{
if (cmdname.length==0) {
throw new IllegalArgumentException("invalid empty name for command");
}
try {
val candidateClassName = "commands"+"."+upcase(cmdname)+"$";
val candidateClass = Class.forName(candidateClassName);
val singletonField = candidateClass.getField("MODULE$");
singletonField.get(null);
}catch{
case ex: ClassNotFoundException => findJavaCommandClass(cmdname);
case ex: NoSuchFieldException => throw new IllegalArgumentException(cmdname+" is not a scala object ");
}
}
def findJavaCommandClass(cmdname:String):AnyRef =
try {
val candidateClassName = "commands"+"."+upcase(cmdname);
val candidateClass = Class.forName(candidateClassName);
candidateClass.newInstance().asInstanceOf[AnyRef]
} catch {
case ex: ClassNotFoundException => throw new IllegalStateException("Can't find class or object for command "+cmdname);
}
def upcase(s:String):String = s.patch(0,Seq(s.charAt(0).toUpper),1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment