PageRenderTime 27ms CodeModel.GetById 18ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/rest/ViewWriter.scala

http://github.com/scalate/scalate
Scala | 146 lines | 77 code | 22 blank | 47 comment | 7 complexity | 5ffcd4c5178f1d405a5a27c80e60b51e 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.rest
 19
 20/**
 21 * Copyright (C) 2009-2010 the original author or authors.
 22 * See the notice.md file distributed with this work for additional
 23 * information regarding copyright ownership.
 24 *
 25 * Licensed under the Apache License, Version 2.0 (the "License");
 26 * you may not use this file except in compliance with the License.
 27 * You may obtain a copy of the License at
 28 *
 29 *     http://www.apache.org/licenses/LICENSE-2.0
 30 *
 31 * Unless required by applicable law or agreed to in writing, software
 32 * distributed under the License is distributed on an "AS IS" BASIS,
 33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 34 * See the License for the specific language governing permissions and
 35 * limitations under the License.
 36 */
 37
 38import java.io.OutputStream
 39import java.lang.reflect.Type
 40import javax.ws.rs.ext.{MessageBodyWriter, Provider}
 41import javax.servlet.ServletContext
 42import javax.ws.rs.core.{Context, MultivaluedMap, MediaType}
 43
 44import com.sun.jersey.api.core.ExtendedUriInfo
 45import com.sun.jersey.api.container.ContainerException
 46
 47import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
 48import java.lang.{String, Class}
 49import java.lang.annotation.Annotation
 50import org.fusesource.scalate.support.TemplateFinder
 51import org.fusesource.scalate.servlet.{ServletTemplateEngine, ServletHelper, TemplateEngineServlet}
 52import org.fusesource.scalate.util.{Log, ResourceNotFoundException, Logging}
 53
 54object ViewWriter extends Log
 55
 56/**
 57 * Renders a [[org.fusesource.scalate.rest.View]] using the Scalate template engine 
 58 *
 59 * @version $Revision : 1.1 $
 60 */
 61@Provider
 62class ViewWriter[T] extends MessageBodyWriter[View[T]] {
 63  import ViewWriter._
 64
 65  @Context
 66  protected var uriInfo: ExtendedUriInfo = _
 67  @Context
 68  protected var _servletContext: ServletContext = _
 69  @Context
 70  protected var request: HttpServletRequest = _
 71  @Context
 72  protected var response: HttpServletResponse = _
 73
 74  protected var errorUris: List[String] = ServletHelper.errorUris()
 75
 76  def isWriteable(aClass: Class[_], aType: Type, annotations: Array[Annotation], mediaType: MediaType) = {
 77    classOf[View[T]].isAssignableFrom(aClass)
 78  }
 79
 80  def getSize(view: View[T], aClass: Class[_], aType: Type, annotations: Array[Annotation], mediaType: MediaType) = -1L
 81
 82
 83  def writeTo(view: View[T], aClass: Class[_], aType: Type, annotations: Array[Annotation], mediaType: MediaType, httpHeaders: MultivaluedMap[String, Object], out: OutputStream): Unit = {
 84    def render(template: String) = TemplateEngineServlet.render(template, engine, servletContext, request, response)
 85
 86    try {
 87      val template = view.uri
 88      finder.findTemplate(template) match {
 89        case Some(name) =>
 90          info("Attempting to generate View for %s", name)
 91          // Ensure headers are committed
 92          //out.flush()
 93          view.model match {
 94            case Some(it) => request.setAttribute("it", it)
 95            case _ =>
 96          }
 97          render(name)
 98
 99        case _ =>
100          throw new ResourceNotFoundException(template)
101      }
102    } catch {
103      case e: Exception =>
104        // lets forward to the error handler
105        var notFound = true
106        for (uri <- errorUris if notFound) {
107          if (servletContext.getResource(uri) != null) {
108
109            // we need to expose all the errors property here...
110            request.setAttribute("javax.servlet.error.exception", e)
111            request.setAttribute("javax.servlet.error.exception_type", e.getClass)
112            request.setAttribute("javax.servlet.error.message", e.getMessage)
113            request.setAttribute("javax.servlet.error.request_uri", request.getRequestURI)
114            request.setAttribute("javax.servlet.error.servlet_name", request.getServerName)
115
116            // TODO how to get the status code???
117            val status = 500
118            request.setAttribute("javax.servlet.error.status_code", status)
119
120            request.setAttribute("it", e)
121            render(uri)
122            notFound = false
123          }
124        }
125        if (notFound) {
126          throw new ContainerException(e)
127        }
128    }
129  }
130
131  protected lazy val finder = new TemplateFinder(engine)
132
133
134  protected def engine = ServletTemplateEngine(servletContext)
135
136  /**
137   * Returns the servlet context injected by JAXRS
138   */
139  protected def servletContext: ServletContext = {
140    if (_servletContext == null) {
141      throw new IllegalArgumentException("servletContext not injected")
142    }
143    _servletContext
144  }
145
146}