I've got a composite component to dynamically call a bean action:
<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>
And I've also defined an ActionListener class to implement security:
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);
}
}
If the action on commandButton is defined in standard way:
<h:commandButton action="#{bean.action}" value="test" />
everything is OK and I'm able to detect bean and action in the listener by its ActionEvent but with composite component and this code I have no information on real action params
I have the same problem if I use brace notation: #{beanName['action']}. In this case, in debug mode I can see the object TagMethodExpression in binding with a MethodExpressionImpl and a VariableMapperImpl where there is the mapping beanName -> "real_bean_name"
It's there a way to get bean and action by ActionEvent if it is generated by a composite component or brace notation?
Thanks!