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

raw.compiler.common.CompilerService.scala Maven / Gradle / Ivy

/*
 * Copyright 2023 RAW Labs S.A.
 *
 * Use of this software is governed by the Business Source License
 * included in the file licenses/BSL.txt.
 *
 * As of the Change Date specified in that file, in accordance with
 * the Business Source License, use of this software will be governed
 * by the Apache License, Version 2.0, included in the file
 * licenses/APL.txt.
 */

package raw.compiler.common

import raw.api.{AuthenticatedUser, RawService}
import raw.compiler.base.ProgramContext
import raw.compiler.jvm.{RawDelegatingURLClassLoader, RawMutableURLClassLoader}
import raw.compiler.scala2.{Scala2CompilerContext, Scala2JvmCompiler}
import raw.config.RawSettings
import raw.creds.CredentialsServiceProvider
import raw.inferrer.InferrerServiceProvider
import raw.runtime._
import raw.sources.SourceContext
import raw.utils.RawConcurrentHashMap

import scala.util.control.NonFatal

class CompilerService(implicit settings: RawSettings) extends RawService {

  private val credentials = CredentialsServiceProvider()

  private val mutableClassLoader = new RawMutableURLClassLoader(getClass.getClassLoader)
  private val rawClassLoader = new RawDelegatingURLClassLoader(mutableClassLoader)

  private val scala2JvmCompiler = new Scala2JvmCompiler(mutableClassLoader, rawClassLoader)

  // Map of users to compilers.
  private val compilerCaches = new RawConcurrentHashMap[(AuthenticatedUser, String), Compiler]

  def getCompiler(user: AuthenticatedUser, maybeLanguage: Option[String]): Compiler = {
    val language = maybeLanguage.getOrElse("rql2")
    compilerCaches.getOrElseUpdate((user, language), createCompiler(user, language))
  }

  private def createCompiler(user: AuthenticatedUser, language: String): Compiler = {
    // Initialize source context
    implicit val sourceContext = new SourceContext(user, credentials, settings)

    // Initialize inferrer
    val inferrer = InferrerServiceProvider()

    // Initialize compiler context
    val compilerContext = new Scala2CompilerContext(language, user, sourceContext, inferrer, scala2JvmCompiler)
    try {
      // Initialize compiler. Default language, if not specified is 'rql2'.
      CommonCompilerProvider(language)(compilerContext)
    } catch {
      case NonFatal(ex) =>
        // To not leave hanging inferrer services.
        // This would make tests fail in the afterAll when checking for running services
        inferrer.stop()
        throw ex
    }
  }

  def getProgramContext(
      compiler: Compiler,
      code: String,
      maybeArguments: Option[Array[(String, ParamValue)]],
      environment: ProgramEnvironment
  ): ProgramContext = {
    val runtimeContext = getRuntimeContext(compiler, maybeArguments, environment)
    compiler.getProgramContext(runtimeContext)
  }

  private def getRuntimeContext(
      compiler: Compiler,
      maybeArguments: Option[Array[(String, ParamValue)]],
      environment: ProgramEnvironment
  ): RuntimeContext = {
    val sourceContext = compiler.compilerContext.sourceContext
    new RuntimeContext(
      sourceContext,
      settings,
      maybeArguments,
      environment
    )
  }

  override def doStop(): Unit = {
    compilerCaches.values.foreach(compiler => compiler.compilerContext.inferrer.stop())
    credentials.stop()
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy