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

com.appland.appmap.transform.annotations.HookFactory Maven / Gradle / Ivy

package com.appland.appmap.transform.annotations;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.appland.appmap.util.Logger;

import javassist.CtBehavior;

public class HookFactory {

  private static final List> AGENT_METHOD_FACTORIES =
      new ArrayList>() {
        {
          add(HookAnnotatedSystem::from);
          add(HookClassSystem::from);
        }
      };

  private static final List> APP_METHOD_FACTORIES =
      new ArrayList>() {
        {
          add(HookConditionSystem::from);
        }
      };

  private static final List> ALL_METHOD_FACTORIES =
      new ArrayList>() {
        {
          addAll(AGENT_METHOD_FACTORIES);
          addAll(APP_METHOD_FACTORIES);
        }
      };

  public static final HookFactory AGENT_HOOKS_FACTORY = new HookFactory(AGENT_METHOD_FACTORIES);
  public static final HookFactory APP_HOOKS_FACTORY = new HookFactory(APP_METHOD_FACTORIES);
  public static final HookFactory ALL_HOOKS_FACTORY = new HookFactory(ALL_METHOD_FACTORIES);

  private List> requiredHookSystemFactories = new ArrayList<>();
  private final static List> optionalSystemFactories =
      new ArrayList>() {
        {
          add(ExcludeReceiverSystem::from);
          add(ArgumentArraySystem::from);
        }
      };


  private HookFactory(List> hookSystemFactories) {
    requiredHookSystemFactories.addAll(hookSystemFactories);
  }

  /**
   * Creates a Hook from code behavior.
   *
   * @return a new Hook object if hookBehavior is a valid hook, null otherwise
   */
  public Hook from(CtBehavior hookBehavior) {
    SourceMethodSystem sourceSystem = null;
    for (Function factoryFn : requiredHookSystemFactories) {
      sourceSystem = (SourceMethodSystem)factoryFn.apply(hookBehavior);
      if (sourceSystem != null) {
        break;
      }
    }

    if (sourceSystem == null) {
      return null;
    }

    List optionalSystems = optionalSystemFactories
        .stream()
        .map(factoryFn -> factoryFn.apply(hookBehavior))
        .filter(Objects::nonNull)
        .collect(Collectors.toList());

    Hook hook = new Hook(sourceSystem, optionalSystems, hookBehavior);
    for (ISystem optionalSystem : optionalSystems) {
      if (!optionalSystem.validate(hook)) {
        Logger.println("hook "
            + hook
            + " failed validation from "
            + optionalSystem.getClass().getSimpleName());
        return null;
      }
    }

    return hook;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy