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

http://github.com/scalate/scalate · Scala · 138 lines · 64 code · 21 blank · 53 comment · 3 complexity · 06918e2269fa120d2ceccc0ced6a3b69 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 java.io.File
  20. import javax.servlet.{ ServletConfig, ServletContext }
  21. import org.fusesource.scalate.layout.{ DefaultLayoutStrategy, LayoutStrategy }
  22. import org.fusesource.scalate.util._
  23. import org.fusesource.scalate.{ Binding, TemplateEngine }
  24. import scala.tools.nsc.Global
  25. object ServletTemplateEngine {
  26. val log = Log(getClass)
  27. val templateEngineKey = classOf[ServletTemplateEngine].getName
  28. /**
  29. * Gets the current template engine
  30. *
  31. * @throws IllegalArgumentException if no template engine has been registered with the [[javax.servlet.ServletContext]]
  32. */
  33. def apply(servletContext: ServletContext): ServletTemplateEngine = {
  34. val answer = servletContext.getAttribute(templateEngineKey)
  35. if (answer == null) {
  36. throw new IllegalArgumentException("No ServletTemplateEngine instance registered on ServletContext for key " +
  37. templateEngineKey + ". Are you sure your web application has registered the Scalate TemplateEngineServlet?")
  38. } else {
  39. answer.asInstanceOf[ServletTemplateEngine]
  40. }
  41. }
  42. /**
  43. * Updates the current template engine - called on initialisation of the [[org.fusesource.scalate.servlet.TemplateEngineServlet]]
  44. */
  45. def update(servletContext: ServletContext, templateEngine: ServletTemplateEngine): Unit = {
  46. servletContext.setAttribute(templateEngineKey, templateEngine)
  47. // now lets fire the bootstrap code
  48. templateEngine.boot
  49. }
  50. /**
  51. * Configures the given TemplateEngine to use the default servlet style layout strategy.
  52. *
  53. * The default layout files searched if no layout attribute is defined by a template are:
  54. * * "WEB-INF/scalate/layouts/default.jade"
  55. * * "WEB-INF/scalate/layouts/default.mustache"
  56. * * "WEB-INF/scalate/layouts/default.scaml"
  57. * * "WEB-INF/scalate/layouts/default.ssp"
  58. */
  59. def setLayoutStrategy(engine: TemplateEngine): LayoutStrategy = {
  60. engine.layoutStrategy = new DefaultLayoutStrategy(engine, TemplateEngine.templateTypes.map("/WEB-INF/scalate/layouts/default." + _): _*)
  61. engine.layoutStrategy
  62. }
  63. /**
  64. * Returns the source directories to use for the given config
  65. */
  66. def sourceDirectories(config: Config): List[File] = {
  67. config.getServletContext.getRealPath("/") match {
  68. case path: String => List(new File(path))
  69. case null => List()
  70. }
  71. }
  72. }
  73. /**
  74. * A Servlet based TemplateEngine which initializes itself using a ServletConfig or a FilterConfig.
  75. *
  76. * The default layout files searched if no layout attribute is defined by a template are:
  77. * * "WEB-INF/scalate/layouts/default.jade"
  78. * * "WEB-INF/scalate/layouts/default.mustache"
  79. * * "WEB-INF/scalate/layouts/default.scaml"
  80. * * "WEB-INF/scalate/layouts/default.ssp"
  81. * *
  82. * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  83. */
  84. class ServletTemplateEngine(
  85. val config: Config) extends TemplateEngine(ServletTemplateEngine.sourceDirectories(config)) {
  86. import ServletTemplateEngine.log._
  87. templateDirectories ::= "/WEB-INF"
  88. bindings = List(Binding("context", "_root_." + classOf[ServletRenderContext].getName, true, isImplicit = true))
  89. classpath = buildClassPath
  90. classLoader = Thread.currentThread.getContextClassLoader
  91. resourceLoader = new ServletResourceLoader(config.getServletContext, new FileResourceLoader())
  92. ServletTemplateEngine.setLayoutStrategy(this)
  93. bootInjections = List(this, config.getServletContext)
  94. Option(config.getInitParameter("boot.class")).foreach(clazz => bootClassName = clazz)
  95. info("Scalate template engine using working directory: %s", workingDirectory)
  96. private def buildClassPath(): String = {
  97. val builder = new ClassPathBuilder
  98. // Add optional classpath prefix via web.xml parameter
  99. builder.addEntry(config.getInitParameter("compiler.classpath.prefix"))
  100. // Add containers class path
  101. builder.addPathFrom(getClass)
  102. .addPathFrom(classOf[ServletConfig])
  103. .addPathFrom(classOf[Product])
  104. try {
  105. builder.addPathFrom(classOf[Global])
  106. } catch {
  107. case x: Throwable => // the scala compiler might not be on the path.
  108. }
  109. // Always include WEB-INF/classes and all the JARs in WEB-INF/lib just in case
  110. builder
  111. .addClassesDir(config.getServletContext.getRealPath("/WEB-INF/classes"))
  112. .addLibDir(config.getServletContext.getRealPath("/WEB-INF/lib"))
  113. // Add optional classpath suffix via web.xml parameter
  114. builder.addEntry(config.getInitParameter("compiler.classpath.suffix"))
  115. builder.classPath
  116. }
  117. }