/* * Copyright 2011-2012 Blazebit */ package com.blazebit.blazefaces.facelets; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.el.ELException; import javax.el.MethodExpression; import javax.faces.context.FacesContext; import javax.faces.el.EvaluationException; import javax.faces.el.MethodBinding; import javax.faces.el.MethodNotFoundException; import javax.faces.view.facelets.FaceletContext; import javax.faces.view.facelets.MetaRule; import javax.faces.view.facelets.Metadata; import javax.faces.view.facelets.MetadataTarget; import javax.faces.view.facelets.TagAttribute; import javax.faces.view.facelets.TagAttributeException; /** * Optional Rule for binding Method[Binding|Expression] properties * * @author Mike Kienenberger * @author Jacob Hookom * * Implementation copied from Facelets 1.1.14, as it got hidden by JSF 2.0 */ @SuppressWarnings("deprecation") public class MethodRule extends MetaRule { private final String methodName; private final Class<?> returnTypeClass; private final Class<?>[] params; public MethodRule(String methodName, Class<?> returnTypeClass, Class<?>[] params) { this.methodName = methodName; this.returnTypeClass = returnTypeClass; this.params = params; } public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta) { if (false == name.equals(this.methodName)) { return null; } if (MethodBinding.class.equals(meta.getPropertyType(name))) { Method method = meta.getWriteMethod(name); if (method != null) { return new MethodBindingMetadata(method, attribute, this.returnTypeClass, this.params); } } else if (MethodExpression.class.equals(meta.getPropertyType(name))) { Method method = meta.getWriteMethod(name); if (method != null) { return new MethodExpressionMetadata(method, attribute, this.returnTypeClass, this.params); } } return null; } private static class MethodBindingMetadata extends Metadata { private final Method _method; private final TagAttribute _attribute; private Class<?>[] _paramList; private Class<?> _returnType; public MethodBindingMetadata(Method method, TagAttribute attribute, Class<?> returnType, Class<?>[] paramList) { _method = method; _attribute = attribute; _paramList = paramList; _returnType = returnType; } public void applyMetadata(FaceletContext ctx, Object instance) { MethodExpression expr = _attribute.getMethodExpression(ctx, _returnType, _paramList); try { _method.invoke(instance, new Object[]{new LegacyMethodBinding(expr)}); } catch (InvocationTargetException e) { throw new TagAttributeException(_attribute, e.getCause()); } catch (Exception e) { throw new TagAttributeException(_attribute, e); } } } private static class MethodExpressionMetadata extends Metadata { private final Method _method; private final TagAttribute _attribute; private Class<?>[] _paramList; private Class<?> _returnType; public MethodExpressionMetadata(Method method, TagAttribute attribute, Class<?> returnType, Class<?>[] paramList) { _method = method; _attribute = attribute; _paramList = paramList; _returnType = returnType; } public void applyMetadata(FaceletContext ctx, Object instance) { MethodExpression expr = _attribute.getMethodExpression(ctx, _returnType, _paramList); try { _method.invoke(instance, new Object[]{expr}); } catch (InvocationTargetException e) { throw new TagAttributeException(_attribute, e.getCause()); } catch (Exception e) { throw new TagAttributeException(_attribute, e); } } } private static class LegacyMethodBinding extends MethodBinding implements Serializable { private static final long serialVersionUID = 1L; private final MethodExpression m; public LegacyMethodBinding(MethodExpression m) { this.m = m; } /* * (non-Javadoc) * * @see javax.faces.el.MethodBinding#getType(javax.faces.context.FacesContext) */ public Class<?> getType(FacesContext context) throws MethodNotFoundException { try { return m.getMethodInfo(context.getELContext()).getReturnType(); } catch (javax.el.MethodNotFoundException e) { throw new MethodNotFoundException(e.getMessage(), e.getCause()); } catch (ELException e) { throw new EvaluationException(e.getMessage(), e.getCause()); } } /* * (non-Javadoc) * * @see javax.faces.el.MethodBinding#invoke(javax.faces.context.FacesContext, * java.lang.Object[]) */ public Object invoke(FacesContext context, Object[] params) throws EvaluationException, MethodNotFoundException { try { return m.invoke(context.getELContext(), params); } catch (javax.el.MethodNotFoundException e) { throw new MethodNotFoundException(e.getMessage(), e.getCause()); } catch (ELException e) { throw new EvaluationException(e.getMessage(), e.getCause()); } } @Override public String getExpressionString() { return m.getExpressionString(); } } }