/**
   * Methods on plugin should be called via reflection, because the real plugin object is in parent
   * classloader, but plugin class may be defined in app classloader as well introducing
   * ClassCastException on same class name.
   *
   * @param pluginClass class name of the plugin - it is used to resolve plugin instance from plugin
   *     manager
   * @param appClassLoader application classloader (to resolve plugin instance)
   * @param method method name
   * @param paramTypes param types (as required by reflection)
   * @param params actual param values
   * @return method return value
   */
  public static Object callPluginMethod(
      Class pluginClass,
      ClassLoader appClassLoader,
      String method,
      Class[] paramTypes,
      Object[] params) {
    Object pluginInstance =
        PluginManager.getInstance().getPlugin(pluginClass.getName(), appClassLoader);

    try {
      Method m = pluginInstance.getClass().getDeclaredMethod(method, paramTypes);
      return m.invoke(pluginInstance, params);
    } catch (Exception e) {
      throw new Error(
          String.format("Exception calling method {} on plugin class {}", method, pluginClass), e);
    }
  }
 /**
  * Initialize plugin for a classloader.
  *
  * @param pluginClass identify plugin instance
  * @param appClassLoader classloader in which the plugin should reside
  */
 public static void callInitializePlugin(Class pluginClass, ClassLoader appClassLoader) {
   PluginManager.getInstance()
       .getPluginRegistry()
       .initializePlugin(pluginClass.getName(), appClassLoader);
 }