PageRenderTime 31ms CodeModel.GetById 16ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/support/SiteGenerator.scala

http://github.com/scalate/scalate
Scala | 174 lines | 116 code | 30 blank | 28 comment | 29 complexity | 5b013d103d10f193cc0df44c2af3af51 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.support
 19
 20import java.io.{ File, PrintWriter }
 21import java.{ util => ju }
 22
 23import org.fusesource.scalate._
 24import org.fusesource.scalate.servlet.ServletTemplateEngine
 25import org.fusesource.scalate.util._
 26
 27import scala.collection.JavaConverters._
 28
 29object SiteGenerator extends Log
 30import org.fusesource.scalate.support.SiteGenerator._
 31
 32import scala.language.reflectiveCalls
 33
 34/**
 35 * This class generates static HTML files for your website using the Scalate templates, filters and wiki markups
 36 * you are using.
 37 *
 38 * @author <a href="http://macstrac.blogspot.com">James Strachan</a>
 39 */
 40class SiteGenerator {
 41
 42  var workingDirectory: File = _
 43  var webappDirectory: File = _
 44  var targetDirectory: File = _
 45  var templateProperties: ju.Map[String, String] = _
 46  var bootClassName: String = _
 47  var info: { def apply(v1: String): Unit } = (value: String) => println(value)
 48
 49  def execute() = {
 50    targetDirectory.mkdirs()
 51
 52    if (webappDirectory == null || !webappDirectory.exists) {
 53      throw new IllegalArgumentException("The webappDirectory properly is not properly set")
 54    }
 55
 56    info("Generating static website from Scalate Templates and wiki files...")
 57    info("template properties: " + templateProperties)
 58
 59    val engine = new DummyTemplateEngine(webappDirectory)
 60    engine.classLoader = Thread.currentThread.getContextClassLoader
 61
 62    if (bootClassName != null) {
 63      engine.bootClassName = bootClassName
 64    }
 65
 66    if (workingDirectory != null) {
 67      engine.workingDirectory = workingDirectory
 68      workingDirectory.mkdirs()
 69    }
 70
 71    engine.boot
 72
 73    val attributes: Map[String, Any] = if (templateProperties != null) {
 74      templateProperties.asScala.toMap
 75    } else {
 76      Map()
 77    }
 78
 79    def processFile(file: File, baseuri: String): Unit = {
 80      if (file.isDirectory()) {
 81        if (file.getName != "WEB-INF" && !file.getName.startsWith("_")) {
 82          val children = file.listFiles()
 83          if (children != null) {
 84            for (child <- children) {
 85              if (child.isDirectory) {
 86                processFile(child, baseuri + "/" + child.getName)
 87              } else {
 88                processFile(child, baseuri)
 89              }
 90            }
 91          }
 92        }
 93      } else {
 94        val parts = file.getName.split('.')
 95        if (parts.size > 1 && !file.getName.startsWith("_")) {
 96          val uri = baseuri + "/" + file.getName()
 97          // uri = uri.replace(':', '_')
 98          val ext = parts.last
 99          if (engine.extensions.contains(ext)) {
100
101            try {
102              val source = TemplateSource.fromFile(file, uri)
103              val html = engine.layout(source, attributes)
104              val sourceFile = new File(targetDirectory, appendHtmlPostfix(uri.stripPrefix("/")))
105
106              info("    processing " + file + " with uri: " + uri + " => ")
107              sourceFile.getParentFile.mkdirs
108              //IOUtil.writeBinaryFile(sourceFile, transformHtml(html, uri, rootDir).getBytes("UTF-8"))
109              IOUtil.writeBinaryFile(sourceFile, html.getBytes("UTF-8"))
110            } catch {
111              case e: NoValueSetException => info(e.getMessage + ". Ignored template file due to missing attributes: " + file.getCanonicalPath)
112              case e: VirtualMachineError => throw e
113              case e: ThreadDeath => throw e
114              case e: Throwable => throw new Exception(e.getMessage + ". When processing file: " + file.getCanonicalPath, e)
115            }
116          } else {
117            // let's copy the file across if its not a template
118            debug("    copying " + file + " with uri: " + uri + " extension: " + ext + " not in " + engine.extensions)
119            val sourceFile = new File(targetDirectory, uri.stripPrefix("/"))
120            IOUtil.copy(file, sourceFile)
121          }
122        }
123      }
124    }
125
126    processFile(webappDirectory, "")
127  }
128
129  protected var validFileExtensions = Set("js", "css", "rss", "atom", "htm", "xml", "csv", "json")
130
131  protected def appendHtmlPostfix(uri: String): String = {
132    val answer = Files.dropExtension(uri)
133    val ext = Files.extension(answer)
134    if (validFileExtensions.contains(ext)) {
135      answer
136    } else {
137      answer + ".html"
138    }
139  }
140
141}
142
143class DummyTemplateEngine(
144  rootDirectory: File) extends TemplateEngine(Some(rootDirectory)) {
145
146  override protected def createRenderContext(
147    uri: String,
148    out: PrintWriter) = new DummyRenderContext(uri, this, out)
149
150  private[this] val responseClassName = "_root_." + classOf[DummyResponse].getName
151
152  bindings = List(
153    Binding("context", "_root_." + classOf[DummyRenderContext].getName, true, isImplicit = true),
154    Binding("response", responseClassName, defaultValue = Some("new " + responseClassName + "()")))
155
156  ServletTemplateEngine.setLayoutStrategy(this)
157}
158
159class DummyRenderContext(
160  val _requestUri: String,
161  _engine: TemplateEngine,
162  _out: PrintWriter) extends DefaultRenderContext(_requestUri, _engine, _out) {
163
164  // for static website stuff we must zap the root dir typically
165  override def uri(name: String) = {
166    // lets deal with links to / as being to /index.html
167    val link = if (name == "/") "/index.html" else name
168    Links.convertAbsoluteLinks(link, requestUri)
169  }
170}
171
172class DummyResponse {
173  def setContentType(value: String): Unit = {}
174}