summaryrefslogtreecommitdiffstats
path: root/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/JerseyNode.scala
blob: 92d83f2ecc7609d669aabbc10b550d11ac473345 (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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.di.componentgraph.core

import com.yahoo.component.{ComponentSpecification, ComponentId}
import com.yahoo.container.di.Osgi.RelativePath
import com.yahoo.container.di.config.RestApiContext
import org.osgi.framework.wiring.BundleWiring
import scala.collection.JavaConverters._

import scala.collection.convert.wrapAsJava._
import RestApiContext.BundleInfo
import JerseyNode._
import com.yahoo.container.di.Osgi
import org.osgi.framework.Bundle
import java.net.URL

/**
 * Represents an instance of RestApiContext
 *
 * @author gjoranv
 * @author tonytv
 * @since 5.15
 */
class JerseyNode(componentId: ComponentId,
                 override val configId: String,
                 clazz: Class[_ <: RestApiContext],
                 osgi: Osgi)
  extends ComponentNode(componentId, configId, clazz) {


  override protected def newInstance(): RestApiContext = {
    val instance = super.newInstance()
    val restApiContext = instance.asInstanceOf[RestApiContext]

    val bundles = restApiContext.bundlesConfig.bundles().asScala
    bundles foreach ( bundleConfig => {
        val bundleClasses = osgi.getBundleClasses(
          ComponentSpecification.fromString(bundleConfig.spec()),
          bundleConfig.packages().asScala.toSet)

        restApiContext.addBundle(
          createBundleInfo(bundleClasses.bundle, bundleClasses.classEntries))
    })

    componentsToInject foreach (
      component =>
        restApiContext.addInjectableComponent(component.instanceKey, component.componentId, component.newOrCachedInstance()))

    restApiContext
  }

  override def equals(other: Any): Boolean = {
    super.equals(other) && (other match {
      case that: JerseyNode => componentsToInject == that.componentsToInject
      case _ => false
    })
  }

}

private[core]
object JerseyNode {
  val WebInfUrl = "WebInfUrl"

  def createBundleInfo(bundle: Bundle, classEntries: Iterable[RelativePath]): BundleInfo = {

    val bundleInfo = new BundleInfo(bundle.getSymbolicName,
                                    bundle.getVersion,
                                    bundle.getLocation,
                                    webInfUrl(bundle),
                                    bundle.adapt(classOf[BundleWiring]).getClassLoader)

    bundleInfo.setClassEntries(classEntries)
    bundleInfo
  }


  private def getBundle(osgi: Osgi, bundleSpec: String): Bundle = {

    val bundle = osgi.getBundle(ComponentSpecification.fromString(bundleSpec))
    if (bundle == null)
      throw new IllegalArgumentException("Bundle not found: " + bundleSpec)
    bundle
  }

  private def webInfUrl(bundle: Bundle): URL = {
    val strWebInfUrl = bundle.getHeaders.get(WebInfUrl)

    if (strWebInfUrl == null) null
    else bundle.getEntry(strWebInfUrl)
  }

}