Created
March 12, 2012 21:00
-
-
Save rssh/2024656 to your computer and use it in GitHub Desktop.
run command line program within play 2.0 environment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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