JSF-从复合组件的ActionEvent中获取bean和操作名称



我有一个复合组件可以动态调用bean操作:

<composite:interface>
    <composite:attribute name="actionMethod" method-signature="java.lang.String action()"/>
</composite:interface>
<composite:implementation>
    <p:menubar autoDisplay="false" styleClass="subMenu">
        <p:menuitem>
             <h:commandButton action="#{cc.attrs.actionMethod}" value="#{bundle.CreateSaveLink}" styleClass="smallButton button buttonSave"/>
        </p:menuitem>
    </p:menubar>
</composite:implementation>

我还定义了一个ActionListener类来实现安全性:

public class SecurityActionListener extends ActionListenerImpl implements ActionListener {

    private static final Logger log = Logger.getLogger(SecurityActionListener.class);
    private String isCasEnabled;
    public SecurityActionListener() {
        isCasEnabled = PropertyUtility.isCasEnabled();
    }

    @SuppressWarnings("unused")
    @Override
    public void processAction(final ActionEvent event) {
        if(!isCasEnabled.equals("true")) {
            super.processAction(event);
            return;
        }

        final FacesContext context = FacesContext.getCurrentInstance();
        final Application application = context.getApplication();
        final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
        // Action stuff
        final UIComponent source = event.getComponent();
        final ActionSource actionSource = (ActionSource) source;
        MethodBinding binding;
        binding = actionSource.getAction();
        final String expr = binding.getExpressionString();
        if (!expr.startsWith("#")) {
            super.processAction(event);
            return;
        }
        final int idx = expr.indexOf('.');
        if (idx <0) {
            log.error("Errore nella formattazione della chiamata al metodo: " + expr + ". No '.' found");
            return;
        } 
        final String target = expr.substring(0, idx).substring(2);
        final String t = expr.substring(idx + 1);
        String method = t.substring(0, (t.length() - 1));
        final int idxParams = method.indexOf('(');
        if (idxParams >=0) {
            method = method.substring(0,idxParams);
        }
        final MethodExpression expression = new MethodExpressionMethodBindingAdapter(binding);
        final ELContext elContext = context.getELContext();
        final ExpressionFactory factory = context.getApplication().getExpressionFactory();
        final ValueExpression ve = factory.createValueExpression(elContext, "#{" + target + '}', Object.class);
        final Object result = ve.getValue(elContext);
        // Check if the target method is a secured method
        // and check security accordingly
        final Method[] methods = result.getClass().getMethods();
        for (final Method meth : methods) {
            if (meth.getName().equals(method)) {
                if (meth.isAnnotationPresent(CustomSecurity.class)) {
                    final CustomSecurity securityAnnotation = meth.getAnnotation(CustomSecurity.class);
                    log.debug("Function to check security on: " + securityAnnotation.value()); 
                    SecurityUtility.checkSecurity(securityAnnotation.value());
                } else {
                    super.processAction(event);
                }
                break;
            }
        }
        log.warn("No method: " + method + " found in: " + methods + ", for object: " + result);
    }
}

如果commandButton上的操作是以标准方式定义的:

<h:commandButton action="#{bean.action}" value="test" />

一切都很好,我可以通过它的ActionEvent检测监听器中的bean和action,但对于复合组件和这段代码,我没有关于实际action参数的信息

如果我使用大括号表示法,我也会遇到同样的问题:#{beanName['action']}。在这种情况下,在调试模式下,我可以看到对象TagMethodExpression与MethodExpressionImpl和VariableMapperImpl绑定,其中有映射beanName->"real_bean_name"

如果它是由复合组件或大括号表示法生成的,那么有没有一种方法可以通过ActionEvent获取bean和action?

谢谢!

不是很干净的解决方案,但我使用ActionSource2、MethodExpression和Reflection来访问TagMethodExpression私有字段。。。

final ActionSource2 actionSource = (ActionSource2) source;
MethodExpression expression;
expression = actionSource.getActionExpression();
String exp = expression.getExpressionString();
String trimmed = exp.trim();
// remove ending bracket
trimmed = trimmed.substring(0, trimmed.lastIndexOf("']"));
int openBracket = trimmed.lastIndexOf("['");
String beanName = trimmed.substring(0, openBracket);
StringBuilder builder = new StringBuilder(beanName);
builder.append('.');
builder.append(trimmed.substring(openBracket + 2, trimmed.length()));
String ret = builder.toString();
if (expression instanceof TagMethodExpression) {
    try {
        TagMethodExpression tme = (TagMethodExpression) expression;
        Field f = tme.getClass().getDeclaredField("orig");
        f.setAccessible(true);
        MethodExpression me = (MethodExpression) f.get(tme);
        Field ff = me.getClass().getDeclaredField("varMapper");
        ff.setAccessible(true);
        VariableMapperImpl vmi = (VariableMapperImpl) ff.get(me);
        ValueExpression beanResolveVariable = vmi.resolveVariable(beanName);
        String toString = beanResolveVariable.toString();
        Pattern pattern = Pattern.compile("value="#\{(.*?)\}");
        Matcher matcher = pattern.matcher(toString);
        if(matcher.find()){
            String realBeanName = matcher.group(1);
            ret = ret.replace(beanName, realBeanName);
        }
    } catch (NoSuchFieldException ex) {
        log.error(LogUtility.getStrExc(ex));
    } catch (SecurityException ex) {
        log.error(LogUtility.getStrExc(ex));
    } catch (IllegalAccessException ex) {
        log.error(LogUtility.getStrExc(ex));
    }
}
...

相关内容

  • 没有找到相关文章

最新更新