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

http://github.com/scalate/scalate · Scala · 117 lines · 74 code · 18 blank · 25 comment · 24 complexity · 530053c8997b7f94021f7a829dde09d8 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.support
  19. import java.io.File
  20. import org.fusesource.scalate.servlet.ServletRenderContext
  21. import org.fusesource.scalate.{ Binding, TemplateEngine }
  22. import scala.language.reflectiveCalls
  23. /**
  24. * This class can precompile Scalate templates into JVM
  25. * classes.
  26. *
  27. * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  28. */
  29. class Precompiler {
  30. var sources = Array[File]()
  31. var workingDirectory: File = _
  32. var targetDirectory: File = _
  33. var templates = Array[String]()
  34. var info: { def apply(v1: String): Unit } = (value: String) => println(value)
  35. var contextClass: String = _
  36. var bootClassName: String = _
  37. def execute() = {
  38. if (sources == null || sources.isEmpty) {
  39. throw new IllegalArgumentException("The sources property not properly set")
  40. }
  41. val engine = new TemplateEngine(sources) {
  42. // lets output generated bytecode to the classes directory.
  43. override def bytecodeDirectory = {
  44. if (targetDirectory != null) {
  45. targetDirectory
  46. } else {
  47. super.bytecodeDirectory
  48. }
  49. }
  50. }
  51. engine.classLoader = Thread.currentThread.getContextClassLoader
  52. if (contextClass != null) {
  53. engine.bindings = List(Binding("context", contextClass, true, isImplicit = true))
  54. } else {
  55. engine.bindings = List(Binding("context", "_root_." + classOf[ServletRenderContext].getName, true, isImplicit = true))
  56. }
  57. if (workingDirectory != null) {
  58. engine.workingDirectory = workingDirectory
  59. workingDirectory.mkdirs()
  60. }
  61. if (bootClassName != null) {
  62. engine.bootClassName = bootClassName
  63. }
  64. engine.boot
  65. var paths = List[String]()
  66. for (extension <- engine.codeGenerators.keysIterator; sd <- sources if sd.exists) {
  67. paths = collectUrisWithExtension(sd, "", "." + extension) ::: paths
  68. }
  69. templates.foreach { x =>
  70. paths ::= x
  71. }
  72. info("Precompiling Scalate Templates into Scala classes...")
  73. for (uri <- paths) {
  74. // TODO it would be easier to just generate Source + URI pairs maybe rather than searching again for the source file???
  75. val file = sources.map(new File(_, uri)).find(_.exists).getOrElse(uri)
  76. info(" processing " + file)
  77. engine.load(uri)
  78. }
  79. }
  80. protected def collectUrisWithExtension(basedir: File, baseuri: String, extension: String): List[String] = {
  81. var collected = List[String]()
  82. if (basedir.isDirectory()) {
  83. val files = basedir.listFiles()
  84. if (files != null) {
  85. for (file <- files) {
  86. if (file.isDirectory()) {
  87. collected = collectUrisWithExtension(file, baseuri + "/" + file.getName(), extension) ::: collected
  88. } else {
  89. if (file.getName().endsWith(extension)) {
  90. collected = baseuri + "/" + file.getName() :: collected
  91. } else {
  92. }
  93. }
  94. }
  95. }
  96. }
  97. collected
  98. }
  99. }