summaryrefslogtreecommitdiffstats
path: root/container-jersey2/src/main/scala/com/yahoo/container/servlet/jersey/ComponentGraphProvider.scala
blob: cabde3680a46c709803259c75b2e84aab01bdcf5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.servlet.jersey

import javax.inject.Singleton

import com.yahoo.container.di.config.{ResolveDependencyException, RestApiContext}
import com.yahoo.container.jaxrs.annotation.Component
import org.glassfish.hk2.api.{ServiceHandle, Injectee, InjectionResolver}

/**
 * Resolves jdisc container components for jersey 2 components.
 * Similar to Gjoran's ComponentGraphProvider for jersey 1.
 * @author tonytv
 */
@Singleton //jersey2 requirement: InjectionResolvers must be in the Singleton scope
class ComponentGraphProvider(injectables: Traversable[RestApiContext.Injectable]) extends InjectionResolver[Component] {
  override def resolve(injectee: Injectee, root: ServiceHandle[_]): AnyRef = {
    val wantedClass = injectee.getRequiredType match {
      case c: Class[_] => c
      case unsupported => throw new UnsupportedOperationException("Only classes are supported, got " + unsupported)
    }

    val componentsWithMatchingType = injectables.filter{ injectable =>
        wantedClass.isInstance(injectable.instance) }

    val injectionDescription =
      s"class '$wantedClass' to inject into Jersey resource/provider '${injectee.getInjecteeClass}')"

    if (componentsWithMatchingType.size > 1)
      throw new ResolveDependencyException(s"Multiple components found of $injectionDescription: " +
        componentsWithMatchingType.map(_.id).mkString(","))

    componentsWithMatchingType.headOption.map(_.instance).getOrElse {
      throw new ResolveDependencyException(s"Could not find a component of $injectionDescription.")
    }
  }

  override def isMethodParameterIndicator: Boolean = true
  override def isConstructorParameterIndicator: Boolean = true
}