/**
   * Copy constructor.
   *
   * @param orig Copy to create this instance from.
   * @param newParams Optional array of new parameters to override the ondes from {@code orig}.
   */
  public GridifyArgumentAdapter(GridifyArgument orig, Object... newParams) {
    A.notNull(orig, "orig");

    cls = orig.getMethodClass();
    mtdName = orig.getMethodName();
    target = orig.getTarget();

    types = new Class[orig.getMethodParameterTypes().length];
    params = new Object[orig.getMethodParameters().length];

    System.arraycopy(orig.getMethodParameters(), 0, params, 0, params.length);
    System.arraycopy(orig.getMethodParameterTypes(), 0, types, 0, types.length);

    // Override parameters, if any.
    if (newParams.length > 0) {
      setMethodParameters(newParams);
    }
  }
  /**
   * Provides default implementation for execution of grid-enabled methods. This method assumes that
   * argument passed in is of {@link GridifyArgument} type. It attempts to reflectively execute a
   * method based on information provided in the argument and returns the return value of the
   * method.
   *
   * <p>If some exception occurred during execution, then it will be thrown out of this method.
   *
   * @return {@inheritDoc}
   * @throws GridException {@inheritDoc}
   */
  @Override
  public Object execute() throws GridException {
    GridifyArgument arg = argument(0);

    try {
      // Get public, package, protected, or private method.
      Method mtd =
          arg.getMethodClass()
              .getDeclaredMethod(arg.getMethodName(), arg.getMethodParameterTypes());

      // Attempt to soften access control in case we grid-enabling
      // non-accessible method. Subject to security manager setting.
      if (!mtd.isAccessible())
        try {
          mtd.setAccessible(true);
        } catch (SecurityException e) {
          throw new GridException(
              "Got security exception when attempting to soften access control for "
                  + "@Gridify method: "
                  + mtd,
              e);
        }

      Object obj = null;

      // No need to create an instance for static methods.
      if (!Modifier.isStatic(mtd.getModifiers()))
        // Obtain instance to execute method on.
        obj = arg.getTarget();

      return mtd.invoke(obj, arg.getMethodParameters());
    } catch (InvocationTargetException e) {
      if (e.getTargetException() instanceof GridException)
        throw (GridException) e.getTargetException();

      throw new GridException(
          "Failed to invoke a method due to user exception.", e.getTargetException());
    } catch (IllegalAccessException e) {
      throw new GridException("Failed to access method for execution.", e);
    } catch (NoSuchMethodException e) {
      throw new GridException("Failed to find method for execution.", e);
    }
  }