-
-
Save casualjim/1635451 to your computer and use it in GitHub Desktop.
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 com.matygo.controllers | |
import java.io.File | |
import java.io.PrintWriter | |
import java.io.StringWriter | |
import scala.collection.JavaConversions.mapAsScalaMap | |
import org.scalatra.ScalatraKernel.MultiParamsKey | |
import org.scalatra.ContentTypeInferrer | |
import org.scalatra.util.MultiMap | |
import org.scalatra.CookieSupport | |
import org.scalatra.RouteMatcher | |
import org.scalatra.ScalatraFilter | |
import org.squeryl.PrimitiveTypeMode.transaction | |
import com.matygo.csv.CSVBuilder | |
import com.matygo.exceptions.NotLoggedInException | |
import com.matygo.flow.ExceptionResponse | |
import com.matygo.flow.FlowRequest | |
import com.matygo.flow.Render | |
import com.matygo.implicits.MatygoImplicits | |
import com.matygo.models.system.MatygoFile | |
import com.matygo.models.users.User | |
import com.matygo.models.SproutcoreModel | |
import com.matygo.responses.Destroyed.DestroyResponse | |
import com.matygo.responses.Destroyed | |
import com.matygo.util.MLogFunctions | |
import javax.servlet.http.HttpServletRequest | |
import javax.servlet.http.HttpServletResponse | |
import net.liftweb.json.JsonAST.JObject | |
import net.liftweb.json.JsonAST.JValue | |
import net.liftweb.json.JsonDSL._ | |
import net.liftweb.json.Printer.compact | |
import net.liftweb.json.JsonAST | |
import com.matygo.models.Environment | |
import com.matygo.models.Environments | |
import net.liftweb.json.JsonAST.JString | |
import net.liftweb.json.JsonAST.JArray | |
import com.matygo.util.SQLUtils | |
import org.scalatra.FlashMapSupport | |
import com.matygo.exceptions.NotAuthorizedException | |
import com.matygo.exceptions.NotFoundException | |
import org.scalatra.SweetCookies | |
import org.scalatra.CookieOptions | |
class MatygoController extends ScalatraFilter with CookieSupport with MatygoImplicits with MLogFunctions with MatygoAuthentication with SQLUtils with FlashMapSupport { | |
override def routeBasePath = "/" | |
def json2String(json: JValue) = compact(JsonAST.render(("content" -> json))) | |
protected def currentUser: Option[User] = { | |
val user = userFromRequest | |
if (!(renderLoggedOutContent || allowsLoggedOutContent) && user.isEmpty) throw new NotLoggedInException | |
user | |
} | |
// bindings | |
protected def bindings = request.getOrElseUpdate("bindings", scala.collection.mutable.Map()).asInstanceOf[scala.collection.mutable.Map[String, Any]] | |
private def renderLoggedOutContent = request.get("rendersLoggedOutContent") match { | |
case Some(_) => true | |
case None => false | |
} | |
def rendersLoggedOutContent = { | |
request("rendersLoggedOutContent") = Boolean.box(true) | |
} | |
def allowsLoggedOutContent = false | |
// Scalatra Kernel Overrides | |
def kernelName = this.toString | |
// def servletContext = dispatcher.servletContext | |
// protected override def doNotFound: Action = () => { | |
// response.setStatus(404) | |
// response.getWriter println "Requesting %s but only have %s".format(request.getRequestURI, routes) | |
// } | |
// def requestPath = if (dispatcher.request.getPathInfo != null) dispatcher.request.getPathInfo else dispatcher.request.getServletPath | |
/** Render methods **/ | |
def render(template: String, bindingsA: (String, Any)*) = { | |
for ((k, v) <- flash) bindings(k) = v | |
Render(template, params, bindings, bindingsA: _*) | |
} | |
private def ourContentTypeInferrer: ContentTypeInferrer = { | |
case f: MatygoFile => f.inferredContentType | |
case t: Traversable[_] => t.headOption match { | |
case Some(element) => if (element.isInstanceOf[JObject] || element.isInstanceOf[SproutcoreModel]) "application/json" else "text/html" | |
case None => "text/html" | |
} | |
case _: JValue => "application/json" | |
case _: SproutcoreModel => "application/json" | |
case _: Render => "text/html" | |
case _: DestroyResponse => "application/json" | |
case _: CSVBuilder => "text/csv" | |
case _: String => "text/plain" | |
case _: Array[Byte] => "application/octet-stream" | |
case _ => "text/html" | |
} | |
override protected def contentTypeInferrer: ContentTypeInferrer = ourContentTypeInferrer orElse super.contentTypeInferrer | |
private def ourRenderPipeline: PartialFunction[Any, Any] = { | |
case json: JValue => json2String(json) | |
case t: Traversable[_] => t.headOption match { | |
case Some(element) => { | |
rseq2jvalue(element match { | |
case model: SproutcoreModel => { | |
val ct = t.asInstanceOf[Traversable[SproutcoreModel]] | |
ct.map(_.toJSON(currentUser)) | |
} | |
case json: JValue => { | |
t.asInstanceOf[Traversable[JValue]] | |
} | |
case a: Any => { | |
t.map(e => JString(e.toString())) | |
} | |
}) | |
} | |
case None => JArray(Nil) | |
} | |
case model: SproutcoreModel => transaction(model.toJSON(currentUser)) | |
case render: Render => render.doTemplating | |
case destroyed: DestroyResponse => Destroyed(destroyed) | |
case csv: CSVBuilder => transaction(csv.toCSVString) | |
case f: MatygoFile => f.fileOnDisk | |
} | |
override protected def renderPipeline = ourRenderPipeline orElse super.renderPipeline | |
override protected def renderResponseBody(actionResult: Any) = { | |
request("contentWritten") = Long.box(actionResult match { | |
case array: Array[_] => array.size | |
case f: File => f.length | |
case str: String => str.length | |
case _ => 0 | |
}) | |
super.renderResponseBody(actionResult) | |
} | |
override def handle(request: HttpServletRequest, response: HttpServletResponse) { | |
_request.withValue(request) { | |
_response.withValue(response) { | |
transaction { | |
request("start") = Long.box(System.currentTimeMillis) | |
super.handle(request, response) | |
info(reportProfile) | |
} | |
} | |
} | |
} | |
error { | |
case e => { | |
val (theStatus, message) = ExceptionResponse(e) | |
val json = json2String(message) | |
info("Handled invalid action, sending % : %" % (status, json)) | |
import java.io.{ StringWriter, PrintWriter } | |
e match { | |
case _: NotLoggedInException => () | |
case _: NotAuthorizedException => () | |
case _: NotFoundException => { | |
val stackTrace = e.getStackTrace() | |
val writer = new StringWriter | |
for (i <- 0 to 5) { | |
writer.append(stackTrace(i).toString()) | |
writer.append("\n") | |
} | |
warning(writer.toString()) | |
} | |
case _ => { | |
// log exception if it's not a loggedin one since those happen a lot | |
val writer = new StringWriter | |
e.printStackTrace(new PrintWriter(writer)) | |
error(writer.toString()) | |
// if we are in testing mode lets | |
// shit out the stack trace | |
if (Environment.mode == Environments.Testing) | |
e.printStackTrace() | |
} | |
} | |
status = theStatus | |
message | |
} | |
} | |
/** Render methods **/ | |
// def render(template: String, bindingsA: (String, Any)*) = { | |
// for ((k, v) <- flash) bindings(k) = v | |
// Render(template, params, bindings, bindingsA: _*) | |
// } | |
def req = new FlowRequest(request) | |
/** | |
* Redefining Get/Post/Put/Delete methods to wrap in transaction and register routes with dispatcher | |
* | |
*/ | |
def reportProfile = { | |
val took = System.currentTimeMillis() - request.getOrElse("start", 0).asInstanceOf[Long] | |
"[%, %, % ms, %, %, %]" % (request.getMethod, request.getRequestURI, took, request("contentWritten"), getClass.getName, transaction(userFromRequest.map(_.id).getOrElse(""))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment