/*
* (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library 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.
*
* Contributors:
* <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
*
* $Id: FancyNavigationHandler.java 28924 2008-01-10 14:04:05Z sfermigier $
*/
package org.nuxeo.ecm.platform.ui.web.rest;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import javax.faces.FacesException;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.application.NavigationCase;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.contexts.Contexts;
import org.nuxeo.ecm.platform.ui.web.rest.api.URLPolicyService;
import org.nuxeo.ecm.platform.ui.web.util.BaseURL;
import org.nuxeo.runtime.api.Framework;
import com.sun.faces.util.Util;
/**
* Navigation handler that keeps outcome information available so that it can
* be used for a document view when redirecting to this context.
*
* @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
*/
public class FancyNavigationHandler extends ConfigurableNavigationHandler {
private static final Log log = LogFactory.getLog(FancyNavigationHandler.class);
private final NavigationHandler parent;
public static final String DISABLE_REDIRECT_FOR_URL_REWRITE = FancyNavigationHandler.class.getCanonicalName()
+ ".DISABLE_REDIRECT_FOR_URL_REWRITE";
public FancyNavigationHandler(NavigationHandler navigationHandler) {
parent = navigationHandler;
}
@Override
public void handleNavigation(FacesContext context, String fromAction,
String outcome) {
ExternalContext eContext = context.getExternalContext();
HttpServletRequest httpRequest = (HttpServletRequest) eContext.getRequest();
// put outcome in request params
httpRequest.setAttribute(URLPolicyService.POST_OUTCOME_REQUEST_KEY,
outcome);
URLPolicyService pservice = null;
try {
pservice = Framework.getService(URLPolicyService.class);
pservice.appendParametersToRequest(context);
} catch (Exception e) {
log.error("error occured while appending params to request: ", e);
}
// get old root to check if it's changed
UIViewRoot oldRoot = context.getViewRoot();
parent.handleNavigation(context, fromAction, outcome);
UIViewRoot newRoot = context.getViewRoot();
boolean rootChanged = !oldRoot.equals(newRoot);
if (outcome != null && !context.getResponseComplete() && !rootChanged
&& pservice != null && Framework.isDevModeSet()) {
// navigation was not done => maybe a hot reload issue: perform
// navigation again using local code because it uses
// information from the StaticNavigationHandler that is
// hot-reloaded correctly
// TODO: check if still relevant in JSF2
handleHotReloadNavigation(pservice, context, fromAction, outcome);
}
Object disable = httpRequest.getAttribute(DISABLE_REDIRECT_FOR_URL_REWRITE);
if (Boolean.TRUE.equals(disable)) {
// avoid redirect
return;
}
// force redirect if outcome is null so that url can be
// re-written except in an ajax request
boolean ajaxRequest = context.getPartialViewContext().isAjaxRequest();
if (outcome == null && !ajaxRequest && !context.getResponseComplete()) {
String url = httpRequest.getRequestURL().toString();
String localUrl = BaseURL.getServerURL(httpRequest, true);
String baseUrl = BaseURL.getServerURL(httpRequest, false);
if (localUrl != null && !localUrl.equals(baseUrl)) {
url = url.replaceFirst(localUrl, baseUrl);
}
if (Contexts.isEventContextActive()) {
// add conversation id before redirect
url = RestHelper.addMainConversationParameters(url);
}
try {
eContext.redirect(url);
} catch (IOException e) {
// do nothing...
log.error(e, e);
}
}
}
protected void handleHotReloadNavigation(URLPolicyService pservice,
FacesContext context, String fromAction, String outcome) {
String viewId = pservice.getViewIdFromOutcome(outcome, null);
ExternalContext extContext = context.getExternalContext();
if (viewId != null) {
ViewHandler viewHandler = Util.getViewHandler(context);
// always redirect
String newPath = viewHandler.getActionURL(context, viewId);
try {
extContext.redirect(extContext.encodeActionURL(newPath));
} catch (java.io.IOException ioe) {
throw new FacesException(ioe.getMessage(), ioe);
}
context.responseComplete();
}
}
@Override
public NavigationCase getNavigationCase(FacesContext context,
String fromAction, String outcome) {
if (parent instanceof ConfigurableNavigationHandler) {
return ((ConfigurableNavigationHandler) parent).getNavigationCase(
context, fromAction, outcome);
}
return null;
}
@Override
public Map<String, Set<NavigationCase>> getNavigationCases() {
if (parent instanceof ConfigurableNavigationHandler) {
return ((ConfigurableNavigationHandler) parent).getNavigationCases();
}
return null;
}
}