Created
January 18, 2012 20:00
-
-
Save joegaudet/1635195 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: _*) | |
} | |
override protected def contentTypeInferrer: 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 renderResponseBody(actionResult: Any) { | |
actionResult match { | |
case json: JValue => renderResponseBody(json2String(json)) | |
case t: Traversable[_] => t.headOption match { | |
case Some(element) => { | |
renderResponseBody(seq2jvalue(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 => renderResponseBody(seq2jvalue(List[JValue]())) | |
} | |
case model: SproutcoreModel => renderResponseBody(json2String(transaction(model.toJSON(currentUser)))) | |
case render: Render => renderResponseBody(render.doTemplating) | |
case destroyed: DestroyResponse => renderResponseBody(Destroyed(destroyed)) | |
case csv: CSVBuilder => renderResponseBody(transaction(csv.toCSVString)) | |
case f: MatygoFile => renderResponse(f.fileOnDisk) | |
case _ => { | |
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) { | |
// As default, the servlet tries to decode params with ISO_8859-1. | |
// It causes an EOFException if params are actually encoded with the other code (such as UTF-8) | |
if (request.getCharacterEncoding == null) | |
request.setCharacterEncoding(defaultCharacterEncoding) | |
val realMultiParams = request.getParameterMap.asInstanceOf[java.util.Map[String, Array[String]]].toMap | |
.transform { (k, v) => v: Seq[String] } | |
response.setCharacterEncoding(defaultCharacterEncoding) | |
_request.withValue(request) { | |
_response.withValue(response) { | |
transaction { | |
try { | |
request("start") = Long.box(System.currentTimeMillis) | |
request(MultiParamsKey) = MultiMap(Map() ++ realMultiParams) | |
executeRoutes() // IPC: taken out because I needed the extension point | |
// request.getSession.setAttribute(FlashSupport.sessionKey, flash) | |
// flash.sweep() | |
info(reportProfile) | |
} | |
catch { | |
case e => { | |
val (status, 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() | |
} | |
} | |
response.setStatus(status) | |
response.getWriter.print(json) | |
} | |
} | |
} | |
} | |
} | |
} | |
/** 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