PageRenderTime 30ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/servlet/TemplateEngineFilter.scala

http://github.com/scalate/scalate
Scala | 154 lines | 92 code | 23 blank | 39 comment | 0 complexity | 95cd1d7880ecc042e67461003a59fe78 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.servlet
  19. import javax.servlet._
  20. import javax.servlet.http.{ HttpServletRequest, HttpServletRequestWrapper, HttpServletResponse }
  21. import org.fusesource.scalate.support.TemplateFinder
  22. import org.fusesource.scalate.util.Log
  23. object TemplateEngineFilter extends Log
  24. /**
  25. * Servlet filter which auto routes to the scalate engines for paths which have a scalate template
  26. * defined.
  27. *
  28. * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  29. */
  30. class TemplateEngineFilter extends Filter {
  31. import TemplateEngineFilter._
  32. var config: FilterConfig = _
  33. var engine: ServletTemplateEngine = _
  34. var finder: TemplateFinder = _
  35. var errorUris: List[String] = ServletHelper.errorUris()
  36. /**
  37. * Called by the servlet engine to create the template engine and configure this filter
  38. */
  39. def init(filterConfig: FilterConfig) = {
  40. config = filterConfig
  41. engine = createTemplateEngine(config)
  42. finder = new TemplateFinder(engine)
  43. filterConfig.getInitParameter("replaced-extensions") match {
  44. case null =>
  45. case x =>
  46. finder.replacedExtensions = x.split(":+").toList
  47. }
  48. // register the template engine so they can be easily resolved from elsewhere
  49. ServletTemplateEngine(filterConfig.getServletContext) = engine
  50. }
  51. /**
  52. * Called by the servlet engine on shut down.
  53. */
  54. def destroy = {
  55. }
  56. /**
  57. * Performs the actual filter
  58. */
  59. def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain): Unit = {
  60. (request, response) match {
  61. case (request: HttpServletRequest, response: HttpServletResponse) =>
  62. val request_wrapper = wrap(request)
  63. debug("Checking '%s'", request.getRequestURI)
  64. findTemplate(request.getRequestURI.substring(request.getContextPath.length)) match {
  65. case Some(template) =>
  66. debug("Rendering '%s' using template '%s'", request.getRequestURI, template)
  67. val context = new ServletRenderContext(engine, request_wrapper, response, config.getServletContext)
  68. try {
  69. context.include(template, true)
  70. } catch {
  71. case e: Throwable => showErrorPage(request_wrapper, response, e)
  72. }
  73. case None =>
  74. chain.doFilter(request_wrapper, response)
  75. }
  76. case _ =>
  77. chain.doFilter(request, response)
  78. }
  79. }
  80. def showErrorPage(request: HttpServletRequest, response: HttpServletResponse, e: Throwable): Unit = {
  81. info(e, "failure: %s", e)
  82. // we need to expose all the errors property here...
  83. request.setAttribute("javax.servlet.error.exception", e)
  84. request.setAttribute("javax.servlet.error.exception_type", e.getClass)
  85. request.setAttribute("javax.servlet.error.message", e.getMessage)
  86. request.setAttribute("javax.servlet.error.request_uri", request.getRequestURI)
  87. request.setAttribute("javax.servlet.error.servlet_name", request.getServerName)
  88. request.setAttribute("javax.servlet.error.status_code", 500)
  89. response.setStatus(500)
  90. errorUris.find(x => findTemplate(x).isDefined) match {
  91. case Some(template) =>
  92. val context = new ServletRenderContext(engine, request, response, config.getServletContext)
  93. context.include(template, true)
  94. // since we directly rendered the error page.. remove the attributes
  95. // since they screw /w tomcat.
  96. request.removeAttribute("javax.servlet.error.exception")
  97. request.removeAttribute("javax.servlet.error.exception_type")
  98. request.removeAttribute("javax.servlet.error.message")
  99. request.removeAttribute("javax.servlet.error.request_uri")
  100. request.removeAttribute("javax.servlet.error.servlet_name")
  101. request.removeAttribute("javax.servlet.error.status_code")
  102. case None =>
  103. throw e;
  104. }
  105. }
  106. /**
  107. * Allow derived filters to override and customize the template engine from the configuration
  108. */
  109. protected def createTemplateEngine(config: FilterConfig): ServletTemplateEngine = {
  110. new ServletTemplateEngine(config)
  111. }
  112. protected def findTemplate(name: String) = finder.findTemplate(name)
  113. def wrap(request: HttpServletRequest) = new ScalateServletRequestWrapper(request)
  114. class ScalateServletRequestWrapper(request: HttpServletRequest) extends HttpServletRequestWrapper(request) {
  115. override def getRequestDispatcher(path: String) = {
  116. findTemplate(path).map(new ScalateRequestDispatcher(_)).getOrElse(request.getRequestDispatcher(path))
  117. }
  118. }
  119. class ScalateRequestDispatcher(template: String) extends RequestDispatcher {
  120. def forward(request: ServletRequest, response: ServletResponse): Unit = include(request, response)
  121. def include(request: ServletRequest, response: ServletResponse): Unit = {
  122. (request, response) match {
  123. case (request: HttpServletRequest, response: HttpServletResponse) =>
  124. val context = new ServletRenderContext(engine, wrap(request), response, config.getServletContext)
  125. context.include(template, true)
  126. case _ =>
  127. None
  128. }
  129. }
  130. }
  131. }