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

org.scalajs.jsenv.phantomjs.PhantomJettyClassLoader.scala Maven / Gradle / Ivy

package org.scalajs.jsenv.phantomjs

import org.scalajs.core.tools.io.IO

/** A special [[java.lang.ClassLoader]] to load the Jetty 8 dependency of
 *  [[PhantomJSEnv]] in a private space.
 *
 *  It loads everything that belongs to `JettyWebsocketManager` itself (while
 *  retrieving the requested class file from its parent.
 *  For all other classes, it first tries to load them from `jettyLoader`,
 *  which should only contain the Jetty 8 classpath.
 *  If this fails, it delegates to its parent.
 *
 *  The rationale is, that `JettyWebsocketManager` and its dependees can use
 *  the classes on the Jetty 8 classpath, while they remain hidden from the rest
 *  of the Java world. This allows to load another version of Jetty in the same
 *  JVM for the rest of the project.
 */
final class PhantomJettyClassLoader(jettyLoader: ClassLoader,
    parent: ClassLoader) extends ClassLoader(parent) {

  def this(loader: ClassLoader) =
    this(loader, ClassLoader.getSystemClassLoader())

  /** Classes needed to bridge private jetty classpath and public PhantomJS
   *  Basically everything defined in JettyWebsocketManager.
   */
  private val bridgeClasses = Set(
    "org.scalajs.jsenv.phantomjs.JettyWebsocketManager",
    "org.scalajs.jsenv.phantomjs.JettyWebsocketManager$WSLogger",
    "org.scalajs.jsenv.phantomjs.JettyWebsocketManager$ComWebSocketListener",
    "org.scalajs.jsenv.phantomjs.JettyWebsocketManager$$anon$1",
    "org.scalajs.jsenv.phantomjs.JettyWebsocketManager$$anon$2"
  )

  override protected def loadClass(name: String, resolve: Boolean): Class[_] = {
    if (bridgeClasses.contains(name)) {
      // Load bridgeClasses manually since they must be associated to this
      // class loader, rather than the parent class loader in order to find the
      // jetty classes

      // First check if we have loaded it already
      Option(findLoadedClass(name)) getOrElse {
        val wsManager =
          parent.getResourceAsStream(name.replace('.', '/') + ".class")

        if (wsManager == null) {
          throw new ClassNotFoundException(name)
        } else {
          val buf = IO.readInputStreamToByteArray(wsManager)
          defineClass(name, buf, 0, buf.length)
        }
      }
    } else {
      try {
        jettyLoader.loadClass(name)
      } catch {
        case _: ClassNotFoundException =>
          super.loadClass(name, resolve)
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy