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

io.vertx.lang.kotlin.KotlinVerticleFactory.kt Maven / Gradle / Ivy

/*
 * Copyright 2019 Red Hat, Inc.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 *
 * The Eclipse Public License is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * The Apache License v2.0 is available at
 * http://www.opensource.org/licenses/apache2.0.php
 *
 * You may elect to redistribute this code under either of these licenses.
 */
package io.vertx.lang.kotlin

import io.vertx.core.*
import io.vertx.core.spi.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.descriptorUtils.*
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.*
import java.io.*

open class KotlinVerticleFactory : VerticleFactory {
  override fun prefix() = "kt"

  override fun createVerticle(verticleName: String, classLoader: ClassLoader): Verticle {
    val resourceName = VerticleFactory.removePrefix(verticleName)

    var url = classLoader.getResource(resourceName)
    if (url == null) {
      var f = File(resourceName)
      if (!f.isAbsolute) {
        f = File(System.getProperty("user.dir"), resourceName)
      }
      if (f.exists() && f.isFile) {
        url = f.toURI().toURL()
      }
    }
    if (url == null) {
      throw IllegalStateException("Cannot find verticle script: $verticleName on classpath")
    }

    val verticleClasses = KotlinCompilerHelper.compileKotlinScript(classLoader, prefix() == "kts", url) { _, it ->
      it.kind == ClassKind.CLASS
          && it.modality != Modality.ABSTRACT
          && it.modality != Modality.SEALED
          &&
          (it.defaultType.constructor.supertypes.any { it.isVerticleType() }
              || it.defaultType.supertypes().any { it.isVerticleType() }
              || it is ScriptDescriptor
              )
          && it.effectiveVisibility().publicApi
    }

    return when (verticleClasses.size) {
      0 -> throw IllegalStateException("No verticle classes found in the file")
      1 -> toVerticle(verticleClasses.toList().single())
      else -> CompositeVerticle(verticleClasses.map { it -> toVerticle(it.toPair()) })
    }
  }

  private fun toVerticle(entry : Pair, ClassDescriptor>) : Verticle {
    if (entry.second is ScriptDescriptor) {
      return ScriptVerticle(entry.first)
    } else {
      return entry.first.verticle()
    }
  }

  private fun Class<*>.verticle(): Verticle = newInstance() as Verticle

  private fun KotlinType.isVerticleType() = getJetTypeFqName(false) == "io.vertx.core.Verticle"

  private class CompositeVerticle(val children: List) : Verticle {
    private lateinit var vertx: Vertx

    override fun init(vertx: Vertx, context: Context) {
      this.vertx = vertx
    }

    override fun start(startFuture: Future) {
      CompositeFuture.all(
          children.map { verticle ->
            Future.future().apply {
              vertx.deployVerticle(verticle, this)
            }
          }).setHandler { startFuture.complete() }
    }

    override fun stop(stopFuture: Future) {
    }

    override fun getVertx() = vertx
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy