/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @version * */ package com.joe.jsf.viewHandler; import java.io.IOException; import java.util.Locale; import javax.faces.FacesException; import javax.faces.application.NavigationHandler; import javax.faces.application.ViewHandler; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.el.MethodBinding; import javax.servlet.http.HttpServletRequest; /** * * Action viewHandler. This class intercept renderView() call during 6-th phase. If * request URL is matched to specified prefix, than current NavigationHandler will be * called to perform navigation according to rules. Two specific parameters are taken * into account : <b>action</b> and <b>action-binding</b>. If <b>action-binding</b> exists, * it will be executed first to obtain outcome string, otherwise <b>action</b> parameter * will be used for outcome. * * demo URL: http://localhost:8080/test/action.jsf?action=actions.action * rewrited URL : http://localhost:8080/test/action/actions.action */ public class ActionViewHandler extends ViewHandler { public static final String ACTION_PREFIX_PARAM = "org.joe.jsf.ACTION_PREFX"; public static final String DEFAULT_ACTION_PREFIX = "/action"; private ViewHandler viewHandler; private String actionPrefix = null; public ActionViewHandler(ViewHandler defaultViewHandler) { viewHandler = defaultViewHandler; } public Locale calculateLocale(FacesContext context) { return viewHandler.calculateLocale(context); } public String calculateRenderKitId(FacesContext context) { return viewHandler.calculateRenderKitId(context); } public UIViewRoot createView(FacesContext context, String strUID) { UIViewRoot ret = viewHandler.createView(context, strUID); return ret; } public String getActionURL(FacesContext context, String strUID) { return viewHandler.getActionURL(context, strUID); } public String getResourceURL(FacesContext context, String strUID) { return viewHandler.getResourceURL(context, strUID); } public void renderView(FacesContext context, UIViewRoot viewRoot) throws IOException, FacesException { String viewId = viewRoot.getViewId(); if (!context.getResponseComplete() && isMapped(viewId)) { NavigationHandler nh = context.getApplication().getNavigationHandler(); ViewHandler vh = context.getApplication().getViewHandler(); String action = (String) context.getExternalContext().getRequestParameterMap().get("action"); String outcome = (String) context.getExternalContext().getRequestParameterMap().get("outcome"); if (action!=null) { String method = extractMethodName(action); MethodBinding mb = context.getApplication().createMethodBinding("#{"+action+"}", new Class[0]); outcome = mb.invoke(context, new Object[0]).toString(); nh.handleNavigation(context, method, outcome); if (!context.getResponseComplete() && context.getViewRoot().equals(viewRoot)) { throw new FacesException("No navigation rules from viewId="+viewId+", action="+action+", outcome="+outcome+" found."); } } else { nh.handleNavigation(context, null, outcome); if (!context.getResponseComplete() && context.getViewRoot().equals(viewRoot)) { throw new FacesException("No navigation rules from viewId="+viewId+", outcome="+outcome+" found."); } } if (!context.getResponseComplete()) { vh.renderView(context,context.getViewRoot()); }; } else { viewHandler.renderView(context, viewRoot); } } public UIViewRoot restoreView(FacesContext context, String viewId) { UIViewRoot ret = viewHandler.restoreView(context, viewId); return ret; } public void writeState(FacesContext context) throws IOException { viewHandler.writeState(context); } private synchronized void init(FacesContext context) { HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); actionPrefix = (String) request.getSession().getServletContext().getInitParameter(ACTION_PREFIX_PARAM); if (actionPrefix==null || (actionPrefix!=null && actionPrefix.length()==0)) { actionPrefix = DEFAULT_ACTION_PREFIX; } } private String extractMethodName(String methodBinding) { if (methodBinding!=null && methodBinding.length()>1) { if (methodBinding.charAt(methodBinding.length()-1) == ']') { int pos = methodBinding.lastIndexOf('['); if (pos>0) { return methodBinding.substring(pos+1, methodBinding.length()-1); } else { throw new FacesException("Illegal method binding: "+methodBinding); } } else { int pos = methodBinding.lastIndexOf('.'); if (pos>0) { return methodBinding.substring(pos+1); } else { throw new FacesException("Illegal method binding: "+methodBinding); } } } else { return null; } } private String getActionPrefix() { if (actionPrefix == null) { init(FacesContext.getCurrentInstance()); } return actionPrefix; } private boolean isMapped(String viewId) { if (viewId != null) { return viewId.startsWith(getActionPrefix()); } else { return false; } } }