Ejemplo n.º 1
0
  public int arity(ELContext elctx) {
    if (node instanceof ELNode.LAMBDA) {
      return ((ELNode.LAMBDA) node).vars.length;
    }

    MethodInfo info = node.getMethodInfo(getContext(elctx));
    if (info != null && info.getParamTypes() != null) {
      return info.getParamTypes().length;
    } else {
      return -1;
    }
  }
Ejemplo n.º 2
0
  /**
   * This method wraps a <code>MethodExpression</code> in a <code>Method</code> which can be
   * statically invoked.
   *
   * <p>Since Method is a final class with only a non-public constructor, various reflective tricks
   * have been used to create an instance of this class and make sure it calls the given method
   * expression. It has been tested on the Sun/Oracle JDK versions 6 and 7, and it should work on
   * OpenJDK 6 and 7 as well. Other JDKs might not work.
   *
   * @param context the context used for evaluation of the method expression when it's invoked
   *     later. NOTE, this reference is retained by the returned method.
   * @param methodExpression the method expression to be wrapped
   * @return a Method instance that when invoked causes the wrapped method expression to be invoked.
   */
  public static Method methodExpressionToStaticMethod(
      final ELContext context, final MethodExpression methodExpression) {

    final MethodInfo methodInfo =
        methodExpression.getMethodInfo(FacesContext.getCurrentInstance().getELContext());

    try {
      // Create a Method instance with the signature (return type, name,
      // parameter types) corresponding
      // to the method the MethodExpression references.
      final Constructor<Method> methodConstructor =
          Method.class.getDeclaredConstructor(
              Class.class,
              String.class,
              Class[].class,
              Class.class,
              Class[].class,
              int.class,
              int.class,
              String.class,
              byte[].class,
              byte[].class,
              byte[].class);
      methodConstructor.setAccessible(true);
      final Method staticMethod =
          methodConstructor.newInstance(
              null,
              methodInfo.getName(),
              methodInfo.getParamTypes(),
              methodInfo.getReturnType(),
              null,
              0,
              0,
              null,
              null,
              null,
              null);

      // The Sun/Oracle/OpenJDK Method makes use of a private delegator
      // called MethodAccessor.
      // Though specific to those JDKs, this is what we can use to let our
      // Method instance execute something
      // we want. (simply overriding the invoke method would be much
      // better, but unfortunately Method is final)
      final Class<?> methodAccessorClass = Class.forName("sun.reflect.MethodAccessor");

      // Create a proxy for our MethodAccessor, so we don't have to
      // reference the actual type at compile-time.
      final Object MethodAccessor =
          Proxy.newProxyInstance(
              Method.class.getClassLoader(),
              new Class[] {methodAccessorClass},
              new InvocationHandler() {

                @Override
                public Object invoke(final Object proxy, final Method method, final Object[] args)
                    throws Throwable {

                  Object[] params = null;
                  if (args != null && args.length > 1) {
                    // args[0]
                    // should
                    // be
                    // the
                    // Object
                    // on
                    // which
                    // the
                    // method
                    // is
                    // to
                    // be
                    // invoked
                    // (null
                    // in
                    // case
                    // of
                    // static
                    // call)
                    // args[1]
                    // should
                    // be
                    // the
                    // parameters
                    // for
                    // the
                    // method
                    // invocation
                    // (possibly
                    // empty)
                    params = (Object[]) args[1];
                  } else {
                    params = Hacks.EMPTY_PARAMETERS;
                  }

                  return methodExpression.invoke(context, params);
                }
              });

      final Method setMethodAccessor =
          Method.class.getDeclaredMethod("setMethodAccessor", methodAccessorClass);
      setMethodAccessor.setAccessible(true);
      setMethodAccessor.invoke(staticMethod, MethodAccessor);

      // Another private implementation detail of the Sun/Oracle/OpenJDK
      // Method - unless override is set
      // to true, a couple of nasty language checks are done before
      // invoking the MethodAccessor
      final Field override = AccessibleObject.class.getDeclaredField("override");
      override.setAccessible(true);
      override.set(staticMethod, true);

      return staticMethod;
    } catch (final Exception e) {
      throw new IllegalStateException(e);
    }
  }