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

com.uqbar.apo.Advice.scala Maven / Gradle / Ivy

There is a newer version: 3.6.3
Show newest version
package com.uqbar.apo

import scala.collection.mutable.Buffer
import scala.reflect.Manifest
import com.uqbar.apo.parser.$originalAsigment
import com.uqbar.apo.parser.$originalReader
import com.uqbar.apo.parser.APOParser
import com.uqbar.apo.pointcut.PointCut
import javassist.expr.ExprEditor
import javassist.expr.FieldAccess
import javassist.CtMethod
import javassist.CtClass
import javassist.expr.ConstructorCall
import javassist.CtConstructor

/**
 * Intruduce bytecode para que se pueda interceptar todos los fields del objeto.
 *
 */

class Advice(var pointCut: PointCut, interceptor: Interceptor[_]*) extends ExprEditor {
  /**
   * Lista con FieldAccessInterceptors, para armar el codigo que se va a agregar a los accesors.
   */
  val interceptors = interceptor.toBuffer
  lazy val aopEnabled = APOConfig.isAOPEnable()

  // ***************************
  // ** FieldAccess weaving
  // ***************************

  override def edit(fieldAccess: FieldAccess) {
    var statement = new StringBuffer();
    if (fieldAccess.isWriter()) {
      statement.append($originalAsigment().name)
    }
    if (fieldAccess.isReader()) {
      statement.append($originalReader().name)
    }

    if (fieldAccess.where().getMethodInfo().toString().startsWith("")) {
      print("")
    }

    val isEdit = edit[FieldAccess](fieldAccess, statement, classOf[FieldAccess])
    if (isEdit)
      fieldAccess.replace(APOParser.parse(fieldAccess, statement.toString()))
  }

  def edit(method: CtMethod) {
    var statement = new StringBuffer(method.getSignature())
    edit[CtMethod](method, statement, classOf[CtMethod])
  }

  override def edit(method: ConstructorCall) {
    var statement = new StringBuffer(method.getSignature())
    edit[CtConstructor](method.getConstructor(), statement, classOf[CtConstructor])
  }

  /**
   * @param fieldAccess
   * @param name Name of the field being processed
   */
  def edit[T: Manifest](expr: T, statement: StringBuffer, classType: Class[T]): Boolean = {
    var edit = false;
    if (aopEnabled) {
      try {
        val f = filterInterceptor[T]()
        f.foreach(interceptor => {
          if (pointCut.hasIntercept(expr)) {
            interceptor.intercept(statement, expr)
            edit = true;
          }
        })
      } catch {
        case e: Exception => throw this.getVerbosedException(e, statement.toString(), expr);
      }
    }
    edit
  }

  def apply(ctClass: CtClass) {
    ctClass.instrument(this);
    ctClass.getMethods().foreach(m => this.edit(m))
  }

  /**
   * Evita agregar el aspecto a los field access:
   * 
    *
  • Estáticos. *
  • Que ocurran dentro de un constructor. *
*/ def mustWeave(fieldAcces: FieldAccess): Boolean = { return !fieldAcces.isStatic() && this.aopEnabled; } // *************************** // ** Exception helpers // *************************** def filterInterceptor[T: Manifest](): Buffer[Interceptor[T]] = { this.interceptors.filter(_.getType.contains((manifest[T].erasure))).asInstanceOf[Buffer[Interceptor[T]]] } def getVerbosedException[T](ex: Exception, javaStatement: String, expr: T): RuntimeException = { return new APOException(javaStatement, ex); } def addInterceptor[A](interceptor: Interceptor[A]): Advice = { this.interceptors.append(interceptor); return this; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy