All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.liftweb.http.provider.servlet.containers.Servlet30AsyncProvider.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2010-2011 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.liftweb 
package http 
package provider 
package servlet 
package containers 

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet._

import net.liftweb.common._
import net.liftweb.http._
import net.liftweb.http.provider._
import net.liftweb.http.provider.servlet._
import net.liftweb.util._
import Helpers._


object Servlet30AsyncProvider extends AsyncProviderMeta {
  // cc below gets inferred as a Class[?0] existential.
  import scala.language.existentials

  private lazy val (hasContinuations_?, 
                    cc, 
                    asyncClass, 
                    startAsync, 
                    getResponse, 
                    complete,
                    isSupported) = {
    try {
      val cc = Class.forName("jakarta.servlet.ServletRequest")
      val asyncClass = Class.forName("jakarta.servlet.AsyncContext")
      val startAsync = cc.getMethod("startAsync")
      val getResponse = asyncClass.getMethod("getResponse")
      val complete = asyncClass.getMethod("complete")
      val isSupported = cc.getMethod("isAsyncSupported")
      (true, cc, asyncClass, startAsync, getResponse, complete, isSupported)
    } catch {
      case e: Exception =>
        (false, 
         null, 
         null, 
         null, 
         null, 
         null,
         null)
    }
  }

  def suspendResumeSupport_? : Boolean = {
    hasContinuations_?
  }

  /**
   * return a function that vends the ServletAsyncProvider
   */
  def providerFunction: Box[HTTPRequest => ServletAsyncProvider] =
    Full(req => new Servlet30AsyncProvider(req)).
  filter(i => suspendResumeSupport_?)


}

/**
 * Servlet30AsyncProvider
 *
 * Implemented by using Servlet30 Continuation API
 *
 */
class Servlet30AsyncProvider(req: HTTPRequest) extends ServletAsyncProvider with Loggable {
  import scala.language.reflectiveCalls

  private var asyncCtx: Object = null

  type SetTimeout = {def setTimeout(timeout: Long): Unit;}
  
  import Servlet30AsyncProvider._

  private lazy val servletReq = (req.asInstanceOf[HTTPRequestServlet]).req

  def suspendResumeSupport_? : Boolean = hasContinuations_? && 
  isSupported.invoke(servletReq).asInstanceOf[Boolean]

  def resumeInfo: Option[(Req, LiftResponse)] = None

  def suspend(timeout: Long): RetryState.Value = {
    asyncCtx = startAsync.invoke(servletReq)
    try {
    	val st = asyncCtx.asInstanceOf[SetTimeout]
    	st.setTimeout(0L)
    } catch {
    case e: Exception => logger.error("Servlet 3.0 Async: Failed to set timeout", e)
    }
    logger.trace("Servlet 3.0 suspend")
    RetryState.SUSPENDED
  }

  def resume(what: (Req, LiftResponse)): Boolean = {
    logger.trace("Servlet 3.0 begin resume")
    val httpRes = getResponse.invoke(asyncCtx).asInstanceOf[jakarta.servlet.http.HttpServletResponse]
    val httpResponse = new HTTPResponseServlet(httpRes)
    val liftServlet = req.provider.liftServlet
    try {
    	liftServlet.sendResponse(what._2, httpResponse, what._1)
    	complete.invoke(asyncCtx)
    } catch {
    case e: Exception => logger.error("Servlet 3.0 Async: Couldn't resume thread", e)
    }
    logger.trace("Servlet 3.0 resume")
    true
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy