@Before
  public void before() {
    PowerMockito.mockStatic(FacesContext.class);
    facesContext = mock(FacesContext.class);
    elContext = mock(ELContext.class);
    application = mock(Application.class);
    actionSource2 = mock(UICommand.class);
    methodExpression = mock(MethodExpression.class);
    actionEvent = mock(ActionEvent.class);
    navigationHandler = mock(NavigationHandler.class);

    when(FacesContext.getCurrentInstance()).thenReturn(facesContext);
    when(facesContext.getELContext()).thenReturn(elContext);

    when(actionEvent.getComponent()).thenReturn((UIComponent) actionSource2);
    when(actionSource2.getActionExpression()).thenReturn(methodExpression);

    when(facesContext.getApplication()).thenReturn(application);
    when(application.getNavigationHandler()).thenReturn(navigationHandler);
  }
Example #2
0
  /**
   * @see ViewHandler#retargetMethodExpressions(javax.faces.context.FacesContext,
   *     javax.faces.component.UIComponent)
   */
  @Override
  public void retargetMethodExpressions(FacesContext context, UIComponent topLevelComponent) {
    BeanInfo componentBeanInfo =
        (BeanInfo) topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
    // PENDING(edburns): log error message if componentBeanInfo is null;
    if (null == componentBeanInfo) {
      return;
    }
    PropertyDescriptor attributes[] = componentBeanInfo.getPropertyDescriptors();
    String targets = null, attrName = null, strValue = null, methodSignature = null;
    UIComponent target = null;
    ExpressionFactory expressionFactory = null;
    ValueExpression valueExpression = null;
    MethodExpression toApply = null;
    Class expectedReturnType = null;
    Class expectedParameters[] = null;

    for (PropertyDescriptor cur : attributes) {
      // If the current attribute represents a ValueExpression
      if (null != (valueExpression = (ValueExpression) cur.getValue("type"))) {
        // take no action on this attribute.
        continue;
      }
      // If the current attribute representes a MethodExpression
      if (null != (valueExpression = (ValueExpression) cur.getValue("method-signature"))) {
        methodSignature = (String) valueExpression.getValue(context.getELContext());
        if (null != methodSignature) {

          // This is the name of the attribute on the top level component,
          // and on the inner component.
          if (null != (valueExpression = (ValueExpression) cur.getValue("targets"))) {
            targets = (String) valueExpression.getValue(context.getELContext());
          }

          if (null == targets) {
            targets = cur.getName();
          }

          if (null == targets || 0 == targets.length()) {
            // PENDING error message in page?
            logger.severe("Unable to retarget MethodExpression: " + methodSignature);
            continue;
          }

          String[] targetIds = targets.split(" ");

          for (String curTarget : targetIds) {

            attrName = cur.getName();

            // Find the attribute on the top level component
            valueExpression = (ValueExpression) topLevelComponent.getAttributes().get(attrName);
            if (null == valueExpression) {
              // PENDING error message in page?
              logger.severe(
                  "Unable to find attribute with name \""
                      + attrName
                      + "\" in top level component in consuming page.  "
                      + "Page author error.");
              continue;
            }

            // lazily initialize this local variable
            if (null == expressionFactory) {
              expressionFactory = context.getApplication().getExpressionFactory();
            }

            // If the attribute is one of the pre-defined
            // MethodExpression attributes
            boolean isAction = false,
                isActionListener = false,
                isValidator = false,
                isValueChangeListener = false;
            if ((isAction = attrName.equals("action"))
                || (isActionListener = attrName.equals("actionListener"))
                || (isValidator = attrName.equals("validator"))
                || (isValueChangeListener = attrName.equals("valueChangeListener"))) {
              // This is the inner component to which the attribute should
              // be applied
              target = topLevelComponent.findComponent(curTarget);
              if (null == targets) {
                // PENDING error message in page?
                logger.severe(
                    "Unable to retarget MethodExpression.  "
                        + "Unable to find inner component with id "
                        + targets
                        + ".");
                continue;
              }

              if (isAction) {
                expectedReturnType = Object.class;
                expectedParameters = new Class[] {};
                toApply =
                    expressionFactory.createMethodExpression(
                        context.getELContext(),
                        valueExpression.getExpressionString(),
                        expectedReturnType,
                        expectedParameters);
                ((ActionSource2) target).setActionExpression(toApply);
              } else if (isActionListener) {
                expectedReturnType = Void.TYPE;
                expectedParameters = new Class[] {ActionEvent.class};
                toApply =
                    expressionFactory.createMethodExpression(
                        context.getELContext(),
                        valueExpression.getExpressionString(),
                        expectedReturnType,
                        expectedParameters);
                ((ActionSource2) target)
                    .addActionListener(new MethodExpressionActionListener(toApply));
              } else if (isValidator) {
                expectedReturnType = Void.TYPE;
                expectedParameters =
                    new Class[] {FacesContext.class, UIComponent.class, Object.class};
                toApply =
                    expressionFactory.createMethodExpression(
                        context.getELContext(),
                        valueExpression.getExpressionString(),
                        expectedReturnType,
                        expectedParameters);
                ((EditableValueHolder) target).addValidator(new MethodExpressionValidator(toApply));
              } else if (isValueChangeListener) {
                expectedReturnType = Void.TYPE;
                expectedParameters = new Class[] {ValueChangeEvent.class};
                toApply =
                    expressionFactory.createMethodExpression(
                        context.getELContext(),
                        valueExpression.getExpressionString(),
                        expectedReturnType,
                        expectedParameters);
                ((EditableValueHolder) target)
                    .addValueChangeListener(new MethodExpressionValueChangeListener(toApply));
              }
            } else {
              // There is no explicit methodExpression property on
              // an inner component to which this MethodExpression
              // should be retargeted.  In this case, replace the
              // ValueExpression with a method expresson.

              // Pull apart the methodSignature to derive the
              // expectedReturnType and expectedParameters

              // PENDING(rlubke,jimdriscoll) bulletproof this

              assert (null != methodSignature);
              methodSignature = methodSignature.trim();

              // Get expectedReturnType
              int j, i = methodSignature.indexOf(" ");
              if (-1 != i) {
                strValue = methodSignature.substring(0, i);
                try {
                  expectedReturnType = Util.getTypeFromString(strValue);
                } catch (ClassNotFoundException cnfe) {
                  logger.log(
                      Level.SEVERE,
                      "Unable to determine expected return type for " + methodSignature,
                      cnfe);
                  continue;
                }
              } else {
                logger.severe("Unable to determine expected return type for " + methodSignature);
                continue;
              }

              // derive the arguments
              i = methodSignature.indexOf("(");
              if (-1 != i) {
                j = methodSignature.indexOf(")", i + 1);
                if (-1 != j) {
                  strValue = methodSignature.substring(i + 1, j);
                  if (0 < strValue.length()) {
                    String[] params = strValue.split(",");
                    expectedParameters = new Class[params.length];
                    boolean exceptionThrown = false;
                    for (i = 0; i < params.length; i++) {
                      try {
                        expectedParameters[i] = Util.getTypeFromString(params[i]);
                      } catch (ClassNotFoundException cnfe) {
                        logger.log(
                            Level.SEVERE,
                            "Unable to determine expected return type for " + methodSignature,
                            cnfe);
                        exceptionThrown = true;
                        break;
                      }
                    }
                    if (exceptionThrown) {
                      continue;
                    }

                  } else {
                    expectedParameters = new Class[] {};
                  }
                }
              }

              assert (null != expectedReturnType);
              assert (null != expectedParameters);

              toApply =
                  expressionFactory.createMethodExpression(
                      context.getELContext(),
                      valueExpression.getExpressionString(),
                      expectedReturnType,
                      expectedParameters);
              topLevelComponent.getAttributes().put(attrName, toApply);
            }
          }
        }
      }
    }
  }