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

com.hubspot.jinjava.lib.fn.InjectedContextFunctionProxy Maven / Gradle / Ivy

There is a newer version: 2.7.4
Show newest version
package com.hubspot.jinjava.lib.fn;

import static com.hubspot.jinjava.util.Logging.ENGINE_LOG;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.bytecode.AccessFlag;

import com.google.common.base.Throwables;

public class InjectedContextFunctionProxy {

  public static ELFunctionDefinition defineProxy(String namespace, String name, Method m, Object injectedInstance)
  {
    try {
      ClassPool pool = ClassPool.getDefault();

      String ccName = InjectedContextFunctionProxy.class.getSimpleName() + "$$" + namespace + "$$" + name;
      Class injectedClass = null;

      try {
        injectedClass = InjectedContextFunctionProxy.class.getClassLoader().loadClass(ccName);
      } catch (ClassNotFoundException e) {
        CtClass cc = pool.makeClass(ccName);
        CtClass mc = pool.get(m.getDeclaringClass().getName());

        CtField injectedField = CtField.make(String.format("public static %s injectedField;", m.getDeclaringClass().getName()), cc);
        cc.addField(injectedField);

        CtField injectedMethod = CtField.make(String.format("public static %s delegate;", Method.class.getName()), cc);
        cc.addField(injectedMethod);

        CtMethod ctMethod = mc.getDeclaredMethod(m.getName());

        CtMethod invokeMethod = CtNewMethod.make(Modifier.PUBLIC | Modifier.STATIC, ctMethod.getReturnType(), "invoke",
            ctMethod.getParameterTypes(), ctMethod.getExceptionTypes(), null, cc);
        invokeMethod.setBody("{ return $proceed($$); }", "injectedField", m.getName());

        for (CtClass param : ctMethod.getParameterTypes()) {
          if (param.isArray()) {
            invokeMethod.setModifiers(invokeMethod.getModifiers() | AccessFlag.VARARGS);
            break;
          }
        }

        cc.addMethod(invokeMethod);

        injectedClass = cc.toClass();
        cc.detach();
      }

      injectedClass.getField("injectedField").set(null, injectedInstance);
      injectedClass.getField("delegate").set(null, m);

      Method staticMethod = null;
      for (Method m1 : injectedClass.getMethods()) {
        if (m1.getName().equals("invoke")) {
          staticMethod = m1;
          break;
        }
      }

      return new ELFunctionDefinition(namespace, name, staticMethod);
    } catch (Throwable e) {
      ENGINE_LOG.error("Error creating injected context function", e);
      throw Throwables.propagate(e);
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy