/scalate-core/src/main/scala/org/fusesource/scalate/rest/ViewWriter.scala

http://github.com/scalate/scalate · Scala · 146 lines · 77 code · 22 blank · 47 comment · 7 complexity · 5ffcd4c5178f1d405a5a27c80e60b51e MD5 · raw file

  1. /**
  2. * Copyright (C) 2009-2011 the original author or authors.
  3. * See the notice.md file distributed with this work for additional
  4. * information regarding copyright ownership.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.fusesource.scalate.rest
  19. /**
  20. * Copyright (C) 2009-2010 the original author or authors.
  21. * See the notice.md file distributed with this work for additional
  22. * information regarding copyright ownership.
  23. *
  24. * Licensed under the Apache License, Version 2.0 (the "License");
  25. * you may not use this file except in compliance with the License.
  26. * You may obtain a copy of the License at
  27. *
  28. * http://www.apache.org/licenses/LICENSE-2.0
  29. *
  30. * Unless required by applicable law or agreed to in writing, software
  31. * distributed under the License is distributed on an "AS IS" BASIS,
  32. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  33. * See the License for the specific language governing permissions and
  34. * limitations under the License.
  35. */
  36. import java.io.OutputStream
  37. import java.lang.reflect.Type
  38. import javax.ws.rs.ext.{MessageBodyWriter, Provider}
  39. import javax.servlet.ServletContext
  40. import javax.ws.rs.core.{Context, MultivaluedMap, MediaType}
  41. import com.sun.jersey.api.core.ExtendedUriInfo
  42. import com.sun.jersey.api.container.ContainerException
  43. import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
  44. import java.lang.{String, Class}
  45. import java.lang.annotation.Annotation
  46. import org.fusesource.scalate.support.TemplateFinder
  47. import org.fusesource.scalate.servlet.{ServletTemplateEngine, ServletHelper, TemplateEngineServlet}
  48. import org.fusesource.scalate.util.{Log, ResourceNotFoundException, Logging}
  49. object ViewWriter extends Log
  50. /**
  51. * Renders a [[org.fusesource.scalate.rest.View]] using the Scalate template engine
  52. *
  53. * @version $Revision : 1.1 $
  54. */
  55. @Provider
  56. class ViewWriter[T] extends MessageBodyWriter[View[T]] {
  57. import ViewWriter._
  58. @Context
  59. protected var uriInfo: ExtendedUriInfo = _
  60. @Context
  61. protected var _servletContext: ServletContext = _
  62. @Context
  63. protected var request: HttpServletRequest = _
  64. @Context
  65. protected var response: HttpServletResponse = _
  66. protected var errorUris: List[String] = ServletHelper.errorUris()
  67. def isWriteable(aClass: Class[_], aType: Type, annotations: Array[Annotation], mediaType: MediaType) = {
  68. classOf[View[T]].isAssignableFrom(aClass)
  69. }
  70. def getSize(view: View[T], aClass: Class[_], aType: Type, annotations: Array[Annotation], mediaType: MediaType) = -1L
  71. def writeTo(view: View[T], aClass: Class[_], aType: Type, annotations: Array[Annotation], mediaType: MediaType, httpHeaders: MultivaluedMap[String, Object], out: OutputStream): Unit = {
  72. def render(template: String) = TemplateEngineServlet.render(template, engine, servletContext, request, response)
  73. try {
  74. val template = view.uri
  75. finder.findTemplate(template) match {
  76. case Some(name) =>
  77. info("Attempting to generate View for %s", name)
  78. // Ensure headers are committed
  79. //out.flush()
  80. view.model match {
  81. case Some(it) => request.setAttribute("it", it)
  82. case _ =>
  83. }
  84. render(name)
  85. case _ =>
  86. throw new ResourceNotFoundException(template)
  87. }
  88. } catch {
  89. case e: Exception =>
  90. // lets forward to the error handler
  91. var notFound = true
  92. for (uri <- errorUris if notFound) {
  93. if (servletContext.getResource(uri) != null) {
  94. // we need to expose all the errors property here...
  95. request.setAttribute("javax.servlet.error.exception", e)
  96. request.setAttribute("javax.servlet.error.exception_type", e.getClass)
  97. request.setAttribute("javax.servlet.error.message", e.getMessage)
  98. request.setAttribute("javax.servlet.error.request_uri", request.getRequestURI)
  99. request.setAttribute("javax.servlet.error.servlet_name", request.getServerName)
  100. // TODO how to get the status code???
  101. val status = 500
  102. request.setAttribute("javax.servlet.error.status_code", status)
  103. request.setAttribute("it", e)
  104. render(uri)
  105. notFound = false
  106. }
  107. }
  108. if (notFound) {
  109. throw new ContainerException(e)
  110. }
  111. }
  112. }
  113. protected lazy val finder = new TemplateFinder(engine)
  114. protected def engine = ServletTemplateEngine(servletContext)
  115. /**
  116. * Returns the servlet context injected by JAXRS
  117. */
  118. protected def servletContext: ServletContext = {
  119. if (_servletContext == null) {
  120. throw new IllegalArgumentException("servletContext not injected")
  121. }
  122. _servletContext
  123. }
  124. }