Merge with 9882f1d06588145a1118a6d2e6405ba66b7902b5
authorplehegar
Mon, 22 Aug 2011 17:43:01 -0400
changeset 17 690206ecf35d
parent 16 2dd02aa984d7 (current diff)
parent 15 9882f1d06588 (diff)
child 18 bbf5d4d40055
child 27 f00302656b5d
Merge with 9882f1d06588145a1118a6d2e6405ba66b7902b5
--- a/src/main/scala/Main.scala	Mon Aug 22 17:40:33 2011 -0400
+++ b/src/main/scala/Main.scala	Mon Aug 22 17:43:01 2011 -0400
@@ -5,15 +5,65 @@
 import unfiltered.scalate._
 import unfiltered.jetty._
 
-import java.io.File
-
+import java.io.{File, FileWriter}
+import org.fusesource.scalate.TemplateEngine
+import java.util.jar._
+import scala.collection.JavaConversions._
+import scala.io.Source
+import java.net.{URL, URLDecoder}
 import org.slf4j.{Logger, LoggerFactory}
 
-
 object VirtualTrainerApp {
 
   val logger:Logger = LoggerFactory.getLogger(this.getClass)
 
+  val clazz:Class[_] = this.getClass
+  val classloader = this.getClass.getClassLoader
+  
+  /** http://www.uofr.net/~greg/java/get-resource-listing.html
+   */
+  def getResourceListing(path:String):List[String] = {
+    var dirURL:URL = classloader.getResource(path)
+    if (dirURL != null && dirURL.getProtocol == "file") {
+      /* A file path: easy enough */
+      new File(dirURL.toURI).list.toList
+    } else {
+      if (dirURL == null) {
+        val me = clazz.getName().replace(".", "/")+".class"
+        dirURL = classloader.getResource(me)
+      }
+      if (dirURL.getProtocol == "jar") {
+        val jarPath = dirURL.getPath.substring(5, dirURL.getPath().indexOf("!"))
+        val jar:JarFile = new JarFile(URLDecoder.decode(jarPath, "UTF-8"))
+        val entries = jar.entries filter { _.getName startsWith path } map { e => {
+          var entry = e.getName substring path.length
+          val checkSubdir = entry indexOf "/"
+          if (checkSubdir >= 0) entry = entry.substring(0, checkSubdir)
+          entry
+        } }
+        entries filterNot { _.isEmpty } toList
+      } else
+        sys.error("Cannot list files for URL "+dirURL);
+    }
+  }
+  
+  /** extract a path found in the classpath
+   * 
+   *  @return the file on disk
+   */
+  def fromClasspath(path:String):File = {
+    val dir = new File("/tmp", "virtual-trainer-" + scala.util.Random.nextInt(10000).toString)
+    if (! dir.mkdir()) logger.error("Couldn't extract %s from jar to %s" format (path, dir.getAbsolutePath))
+    val entries = getResourceListing(path) foreach { entry =>
+      val url = classloader.getResource(path + entry)
+      val content = Source.fromURL(url, "UTF-8").getLines.mkString("\n")
+      val writer = new FileWriter(new File(dir, entry))
+      writer.write(content)
+      writer.close()
+    }
+    dir
+  }
+  
   def main(args: Array[String]) {
     
     val port = args.toList.headOption map { _.toInt } getOrElse 2719
@@ -21,9 +71,18 @@
     val echo = unfiltered.filter.Planify {
       case Path(Seg(p :: Nil)) => ResponseString(p)
     }
+    
+    val engine = {
+      val templates = fromClasspath("templates/")
+      logger.debug("Template directory extracted at " + templates.getAbsolutePath)
+      val templateDirs = List(templates)
+      val scalateMode = "production"
+      new TemplateEngine(templateDirs, scalateMode)
+    }
 
     val app = unfiltered.filter.Planify {
-       case req @ Path(Seg("tracker" :: Nil)) => Ok ~> ContentType("application/xhtml+xml") ~> Scalate(req, "geolocation.ssp")
+       case req @ Path(Seg("tracker" :: Nil)) =>
+         Ok ~> ContentType("application/xhtml+xml") ~> Scalate(req, "geolocation.ssp")(engine)
        case req @ POST(Path(Seg("user" :: user :: "run" :: Nil))) => {
          val body = Body.string(req)
          logger.info(body)
@@ -47,9 +106,9 @@
         def init(filterConfig:FilterConfig):Unit = ()
       }
     }.context("/scripts"){ ctx:ContextBuilder =>
-      ctx.resources(new File("src/main/resources/scripts").toURI.toURL)
+      ctx.resources(fromClasspath("scripts/").toURI.toURL)
     }.context("/styles"){ ctx:ContextBuilder =>
-      ctx.resources(new File("src/main/resources/styles").toURI.toURL)
+      ctx.resources(fromClasspath("styles/").toURI.toURL)
     }.filter(app).filter(echo).run()