/* * Copyright (C) 2006 - original idea by Andrew Robinson * http://drewdev.blogspot.ca/2006/06/creating-composite-controls-with-jsf.html * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.richfaces.photoalbum.util; import java.io.IOException; import javax.el.ELContext; import javax.el.ELException; import javax.el.ExpressionFactory; import javax.el.MethodExpression; import javax.el.MethodInfo; import javax.el.ValueExpression; import javax.el.VariableMapper; import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.event.ActionEvent; import javax.faces.view.facelets.FaceletContext; import javax.faces.view.facelets.FaceletException; import javax.faces.view.facelets.TagConfig; import javax.faces.view.facelets.TagHandler; public class ActionMapperTagHandler extends TagHandler { private static final Class<?>[] ACTION_PARAM_TYPES = new Class[0]; private static final Class<?>[] ACTION_LISTENER_PARAM_TYPES = new Class[] { ActionEvent.class }; private static final MethodInfo NOOP_ACTION_INFO = new MethodInfo("$$$noOpAction", String.class, ACTION_PARAM_TYPES); private static final MethodExpression NOOP_ACTION_EXPRESSION = new MethodExpression() { /** * */ private static final long serialVersionUID = 8901807727474303033L; @Override public MethodInfo getMethodInfo(ELContext context) { return NOOP_ACTION_INFO; } @Override public Object invoke(ELContext context, Object[] params) { return null; } @SuppressWarnings("all") @Override public String getExpressionString() { return "#{" + NOOP_ACTION_INFO.getName() + "}"; } @Override public boolean isLiteralText() { return false; } @Override public boolean equals(Object obj) { return this == obj; } @Override public int hashCode() { return NOOP_ACTION_INFO.hashCode(); } }; private static final MethodInfo NOOP_ACTION_LISTENER_INFO = new MethodInfo("$$$noOpActionListener", Void.class, ACTION_LISTENER_PARAM_TYPES); private static final MethodExpression NOOP_ACTION_LISTENER_EXPRESSION = new MethodExpression() { /** * */ private static final long serialVersionUID = 6246200728401095532L; @Override public MethodInfo getMethodInfo(ELContext context) { return NOOP_ACTION_LISTENER_INFO; } @Override public Object invoke(ELContext context, Object[] params) { return null; } @SuppressWarnings("all") @Override public String getExpressionString() { return "#{" + NOOP_ACTION_LISTENER_INFO.getName() + "}"; } @Override public boolean isLiteralText() { return false; } @Override public boolean equals(Object obj) { return this == obj; } @Override public int hashCode() { return NOOP_ACTION_LISTENER_INFO.hashCode(); } }; private static final String ACTION = "action"; private static final String ACTION_LISTENER = "actionListener"; private static final String MAPPED_ACTION = "mappedAction"; private static final String MAPPED_ACTION_LISTENER = "mappedActionListener"; public ActionMapperTagHandler(TagConfig config) { super(config); } private MethodExpression remap(FaceletContext faceletContext, String varName, Class<?> expectedReturnType, Class<?>[] expectedParamTypes) { MethodExpression result = null; VariableMapper mapper = faceletContext.getVariableMapper(); ValueExpression valueExpression = mapper.resolveVariable(varName); if (valueExpression != null) { ExpressionFactory ef = faceletContext.getExpressionFactory(); ELContext elContext = faceletContext.getFacesContext().getELContext(); result = ef.createMethodExpression(elContext, valueExpression.getExpressionString(), expectedReturnType, expectedParamTypes); } return result; } public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, ELException { MethodExpression actionExpression = remap(ctx, ACTION, String.class, ACTION_PARAM_TYPES); MethodExpression actionListenerExpression = remap(ctx, ACTION_LISTENER, null, ACTION_LISTENER_PARAM_TYPES); VariableMapper initialVarMapper = ctx.getVariableMapper(); try { if (actionExpression == null) { actionExpression = NOOP_ACTION_EXPRESSION; } initialVarMapper.setVariable(MAPPED_ACTION, ctx.getExpressionFactory().createValueExpression(actionExpression, MethodExpression.class)); if (actionListenerExpression == null) { actionListenerExpression = NOOP_ACTION_LISTENER_EXPRESSION; } initialVarMapper.setVariable(MAPPED_ACTION_LISTENER, ctx.getExpressionFactory().createValueExpression(actionListenerExpression, MethodExpression.class)); ctx.setVariableMapper(initialVarMapper); nextHandler.apply(ctx, parent); } finally { ctx.setVariableMapper(initialVarMapper); } } }