import com.sun.jersey.api.ParamException.QueryParamException
import com.sun.jersey.api.core.HttpContext
import com.sun.jersey.api.model.Parameter
import com.sun.jersey.core.spi.component.{ComponentContext, ComponentScope}
import com.sun.jersey.spi.inject.{Injectable, InjectableProvider}
import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable
import com.sun.jersey.server.impl.model.parameter.multivalued.MultivaluedParameterExtractor
import com.sun.jersey.server.impl.model.parameter.multivalued.ExtractorContainerException
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.ext.Provider
import org.springframework.stereotype.Component
@Provider
@Component
class ScalaQueryParamInjectableProvider extends InjectableProvider[QueryParam, Parameter] {
def getScope = ComponentScope.PerRequest
def getInjectable(ic: ComponentContext, a: QueryParam, c: Parameter): Injectable[_] = {
val paramName = c.getSourceName
if (paramName == null || paramName.isEmpty) {
null
} else {
ScalaQueryParamExtractor(c) match {
case null => null
case e => new ScalaQueryParamInjectable(e, !c.isEncoded)
}
}
}
}
class ScalaQueryParamInjectable(extractor: MultivaluedParameterExtractor, decode: Boolean)
extends AbstractHttpContextInjectable[Object] {
def getValue(c: HttpContext): Object = try {
extractor.extract(c.getUriInfo.getQueryParameters(decode))
} catch {
case e: ExtractorContainerException => throw new QueryParamException(e.getCause, extractor.getName,
extractor.getDefaultStringValue)
}
}
object ScalaQueryParamExtractor {
def apply(p: Parameter): MultivaluedParameterExtractor = {
val klass = p.getParameterClass
if (klass == classOf[Option[Int]])
new ScalaIntOptionExtractor(p)
else
null
}
}
abstract class BaseScalaOptionExtractor[T](p: Parameter) extends MultivaluedParameterExtractor {
val defaultValue = convert(p.getDefaultValue, None)
def getName = p.getSourceName
def getDefaultStringValue = p.getDefaultValue
def extract(parameters: MultivaluedMap[String, String]) =
convert(parameters.getFirst(p.getSourceName), defaultValue)
def convert(original: String, default: Option[T]): Option[T]
}
class ScalaIntOptionExtractor(p: Parameter) extends BaseScalaOptionExtractor[Int](p) {
def convert(original: String, default: Option[Int]): Option[Int] = original match {
case null => default
case x => try {
Some(x.toInt)
} catch {
case e: NumberFormatException => throw new ExtractorContainerException("not an int", e)
}
}
}