PageRenderTime 27ms CodeModel.GetById 15ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

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