Package org.gap.jseed

Source Code of org.gap.jseed.Injector

package org.gap.jseed;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.Modifier;
import javassist.NotFoundException;

/**
* This object is responsible for delegating the code injection based on
* class {@code Annotation}s, method {@code Annotation}s or field {@code Annotation}s.
*
* @author gpelcha
* @see ClassInjector
* @see MethodInjector
* @see FieldInjector
*/
class Injector implements Configuration{
  private static ClassPool POOL;
  private SubClassFactory factory;
 
  private ClassInjector classInjector;
  private MethodInjector methodInjector;
  private FieldInjector fieldInjector;
 
  static {
    try {
      POOL = ClassPool.getDefault();
    } catch (RuntimeException e) {
      e.printStackTrace();
      throw e;
    }
  }

  public Injector() {
    factory = new SubClassFactory(POOL);
   
    classInjector = new ClassInjector();
    methodInjector = new MethodInjector();
    fieldInjector = new FieldInjector();
  }
 
  /**
   * Injects the abstraction with an implementation that can be instantiated.
   * @param <T>
   * @param type
   * @return
   * @throws InjectCodeException unable to inject code.
   */
  public <T> Class<? extends T> inject(Class<T> type){
    return inject(null, type);
  }
 
  /**
   *
   * @param <T>
   * @param annotation specifies the class annotation to be used.
   * @param type
   * @return
   */
  @SuppressWarnings("unchecked")
  public <T> Class<? extends T> inject(Class<? extends Annotation> annotation, Class<T> type) {
    try {
      Class<? extends T> result = null;
      CtClass abstraction = null;
      try {
        abstraction = POOL.get(type.getName());
      }
      catch (NotFoundException e) {
        POOL.insertClassPath(new ClassClassPath(type));
        abstraction = POOL.get(type.getName());
      }
      CtClass implementation = factory.createSubClass(type.getName(), abstraction);

      methodInjector.injectBehavior(type, abstraction, implementation);
      if (annotation == null) {
        classInjector.injectBehavior(type, abstraction, implementation);
      } else {
        classInjector.injectBehavior(annotation, type, abstraction, implementation);
      }
      fieldInjector.injectBehavior(type, abstraction, implementation);

      implementation.setModifiers(Modifier.PUBLIC);

      result = (Class<? extends T>)implementation.toClass();

      implementation.prune();

      return result;
    } catch (Exception e) {
      throw new InjectCodeException(e);
    }
  }

  @Override
  public void registerClass(Class<? extends Annotation> annotation, Class<? extends InvocationHandler> handler) {
    classInjector.add(annotation, handler);
  }
 
  public void registerClass(Class<? extends Annotation> annotation, Class<? extends InvocationHandler> handler, Validator validator) {
    classInjector.add(annotation, handler);
    classInjector.validateWith(annotation, validator);
  }
 
  public void registerMethod(Class<? extends Annotation> annotation, Class<? extends InvocationHandler> handler) {
    methodInjector.add(annotation, handler);
  }

  public void registerField(Class<? extends Annotation> annotation, Class<? extends FieldHandler> handler) {
    fieldInjector.add(annotation, handler);
  }
}
TOP

Related Classes of org.gap.jseed.Injector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.