001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 016 * 017 * $Id: FancyNavigationHandler.java 28924 2008-01-10 14:04:05Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.rest; 021 022import java.io.IOException; 023import java.util.Map; 024import java.util.Set; 025 026import javax.faces.FacesException; 027import javax.faces.application.ConfigurableNavigationHandler; 028import javax.faces.application.NavigationCase; 029import javax.faces.application.NavigationHandler; 030import javax.faces.application.ViewHandler; 031import javax.faces.component.UIViewRoot; 032import javax.faces.context.ExternalContext; 033import javax.faces.context.FacesContext; 034import javax.servlet.http.HttpServletRequest; 035 036import org.apache.commons.logging.Log; 037import org.apache.commons.logging.LogFactory; 038import org.jboss.seam.contexts.Contexts; 039import org.nuxeo.ecm.platform.ui.web.rest.api.URLPolicyService; 040import org.nuxeo.ecm.platform.ui.web.util.BaseURL; 041import org.nuxeo.runtime.api.Framework; 042 043import com.sun.faces.util.Util; 044 045/** 046 * Navigation handler that keeps outcome information available so that it can be used for a document view when 047 * redirecting to this context. 048 * 049 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 050 */ 051public class FancyNavigationHandler extends ConfigurableNavigationHandler { 052 053 private static final Log log = LogFactory.getLog(FancyNavigationHandler.class); 054 055 private final NavigationHandler parent; 056 057 public static final String DISABLE_REDIRECT_FOR_URL_REWRITE = FancyNavigationHandler.class.getCanonicalName() 058 + ".DISABLE_REDIRECT_FOR_URL_REWRITE"; 059 060 public FancyNavigationHandler(NavigationHandler navigationHandler) { 061 parent = navigationHandler; 062 } 063 064 @Override 065 public void handleNavigation(FacesContext context, String fromAction, String outcome) { 066 ExternalContext eContext = context.getExternalContext(); 067 HttpServletRequest httpRequest = (HttpServletRequest) eContext.getRequest(); 068 // put outcome in request params 069 httpRequest.setAttribute(URLPolicyService.POST_OUTCOME_REQUEST_KEY, outcome); 070 URLPolicyService pservice = Framework.getService(URLPolicyService.class); 071 pservice.appendParametersToRequest(context); 072 // get old root to check if it's changed 073 UIViewRoot oldRoot = context.getViewRoot(); 074 parent.handleNavigation(context, fromAction, outcome); 075 UIViewRoot newRoot = context.getViewRoot(); 076 boolean rootChanged = !oldRoot.equals(newRoot); 077 if (outcome != null && !context.getResponseComplete() && !rootChanged && pservice != null 078 && Framework.isDevModeSet()) { 079 // navigation was not done => maybe a hot reload issue: perform 080 // navigation again using local code because it uses 081 // information from the StaticNavigationHandler that is 082 // hot-reloaded correctly 083 // TODO: check if still relevant in JSF2 084 handleHotReloadNavigation(pservice, context, fromAction, outcome); 085 } 086 Object disable = httpRequest.getAttribute(DISABLE_REDIRECT_FOR_URL_REWRITE); 087 if (Boolean.TRUE.equals(disable)) { 088 // avoid redirect 089 return; 090 } 091 // force redirect if outcome is null so that url can be 092 // re-written except in an ajax request 093 boolean ajaxRequest = context.getPartialViewContext().isAjaxRequest(); 094 if (outcome == null && !ajaxRequest && !context.getResponseComplete()) { 095 String url = httpRequest.getRequestURL().toString(); 096 String localUrl = BaseURL.getServerURL(httpRequest, true); 097 String baseUrl = BaseURL.getServerURL(httpRequest, false); 098 if (localUrl != null && !localUrl.equals(baseUrl)) { 099 url = url.replaceFirst(localUrl, baseUrl); 100 } 101 if (Contexts.isEventContextActive()) { 102 // strip any jsession id before redirect 103 int jsessionidIndex = url.indexOf(";jsessionid"); 104 if (jsessionidIndex != -1) { 105 url = url.substring(0, jsessionidIndex); 106 } 107 // add conversation id before redirect 108 url = RestHelper.addMainConversationParameters(url); 109 } 110 try { 111 eContext.redirect(url); 112 } catch (IOException e) { 113 // do nothing... 114 log.error(e, e); 115 } 116 } 117 } 118 119 protected void handleHotReloadNavigation(URLPolicyService pservice, FacesContext context, String fromAction, 120 String outcome) { 121 String viewId = pservice.getViewIdFromOutcome(outcome, null); 122 ExternalContext extContext = context.getExternalContext(); 123 if (viewId != null) { 124 ViewHandler viewHandler = Util.getViewHandler(context); 125 // always redirect 126 String newPath = viewHandler.getActionURL(context, viewId); 127 try { 128 extContext.redirect(extContext.encodeActionURL(newPath)); 129 } catch (java.io.IOException ioe) { 130 throw new FacesException(ioe.getMessage(), ioe); 131 } 132 context.responseComplete(); 133 } 134 } 135 136 @Override 137 public NavigationCase getNavigationCase(FacesContext context, String fromAction, String outcome) { 138 if (parent instanceof ConfigurableNavigationHandler) { 139 return ((ConfigurableNavigationHandler) parent).getNavigationCase(context, fromAction, outcome); 140 } 141 return null; 142 } 143 144 @Override 145 public Map<String, Set<NavigationCase>> getNavigationCases() { 146 if (parent instanceof ConfigurableNavigationHandler) { 147 return ((ConfigurableNavigationHandler) parent).getNavigationCases(); 148 } 149 return null; 150 } 151}