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

com.lucidchart.piezo.GeneratorClassLoader.scala Maven / Gradle / Ivy

The newest version!
package com.lucidchart.piezo

import org.objectweb.asm.{ClassWriter, Opcodes, Type}
import org.quartz.{Job, JobExecutionContext}
import org.quartz.spi.ClassLoadHelper
import org.slf4j.LoggerFactory

class DummyJob extends Job {
  def execute(context: JobExecutionContext): Unit = {
    throw new UnsupportedOperationException()
  }
}

class GeneratorClassLoader extends ClassLoader(classOf[GeneratorClassLoader].getClassLoader) with ClassLoadHelper {
  val logger = LoggerFactory.getLogger(this.getClass)

  private[this] def generate(name: String) = {
    val classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS)
    classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(classOf[DummyJob]), null)

    // Minimal constructor that just calls the super constructor and returns.
    val constructorWriter = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null)
    constructorWriter.visitVarInsn(Opcodes.ALOAD, 0)
    constructorWriter.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(classOf[Object]), "", "()V", false)
    constructorWriter.visitInsn(Opcodes.RETURN)
    constructorWriter.visitMaxs(0, 0)
    constructorWriter.visitEnd()

    classWriter.visitEnd()

    classWriter.toByteArray
  }

  def getClassLoader = this

  def loadClass[T](name: String, clazz: Class[T]) = loadClass(name).asInstanceOf[Class[_ <: T]]

  def initialize() = ()

  override def loadClass(name: String): Class[_] = try {
    super.loadClass(name)
  } catch {
    case _: ClassNotFoundException =>
      logger.info(s"Dynamically generated dummy job for $name")
      val bytes = generate(name)
      defineClass(name, bytes, 0, bytes.length)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy