/*
* (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:
* Nuxeo - initial API and implementation
*
* $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
*/
package org.nuxeo.ecm.platform.ui.web.shield;
import java.io.Serializable;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.FacesLifecycle;
import org.jboss.seam.faces.Redirect;
import org.jboss.seam.transaction.Transaction;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.DocumentSecurityException;
import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants;
import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper;
/**
* Error handling interceptor.
* <p>
* Redirects to the good error page if an exception is caught: login page on
* security exception, themed error page on other exceptions and unthemed error
* page when another error is caught while rendering the error page.
*
* @author <a href="mailto:rcaraghin@nuxeo.com">Razvan Caraghin</a>
* @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
* @deprecated No need anymore, error is processed in NuxeoExceptionFilter
*/
@Deprecated
public class NuxeoErrorInterceptor implements Serializable {
private static final long serialVersionUID = 6519836435278721L;
private static final Log log = LogFactory.getLog(NuxeoErrorInterceptor.class);
private static final String GENERIC_ERROR_VIEW_ID = "/generic_error_page.xhtml";
private static final String UNTHEMED_ERROR_VIEW_ID = "/unthemed_generic_error_page.xhtml";
private static final String LOGIN_VIEW_ID = "/login.jsp";
@AroundInvoke
public Object invokeAndWrapExceptions(InvocationContext invocation)
throws Exception {
try {
// log.debug("Before invocation...");
return invocation.proceed();
} catch (Throwable t) {
if (Transaction.instance().isActive()) {
Transaction.instance().setRollbackOnly();
}
FacesContext facesContext = FacesContext.getCurrentInstance();
if (FacesLifecycle.getPhaseId() == PhaseId.RENDER_RESPONSE) {
if (ExceptionHelper.isSecurityError(t)) {
if (facesContext != null) {
Object req = facesContext.getExternalContext().getRequest();
if (req instanceof ServletRequest) {
ServletRequest request = (ServletRequest) req;
request.setAttribute("securityException", t);
}
}
throw new DocumentSecurityException(
"Security Error during call of "
+ invocation.getTarget().toString(), t);
}
}
ClientException cException = new ClientException(t);
// redirect is not allowed during render response phase => throw
// the error without redirecting
if (FacesLifecycle.getPhaseId() == PhaseId.RENDER_RESPONSE) {
if (facesContext != null) {
Object req = facesContext.getExternalContext().getRequest();
if (req instanceof ServletRequest) {
ServletRequest request = (ServletRequest) req;
request.setAttribute("applicationException", cException);
}
}
throw cException;
}
// check if previous page was already an error page to avoid
// redirect cycle
if (facesContext != null) {
ExternalContext externalContext = facesContext.getExternalContext();
if (externalContext != null) {
Map<String, String[]> requestMap = externalContext.getRequestHeaderValuesMap();
if (requestMap != null) {
String[] previousPage = requestMap.get("Referer");
if (previousPage != null && previousPage.length != 0) {
String pageName = previousPage[0];
if (pageName != null
&& pageName.contains("error_page")) {
redirectToErrorPage(UNTHEMED_ERROR_VIEW_ID);
return null;
}
}
}
}
}
String redirectToViewId = null;
try {
log.error("Exception caught, redirecting to the error page...",
cException);
final Context sessionContext = Contexts.getSessionContext();
// set applicationException in session hoping
// ErrorPageActionListener will inject it
sessionContext.set("applicationException", cException);
if (ExceptionHelper.isSecurityError(t)
|| cException.getCause() instanceof DocumentSecurityException) {
redirectToViewId = LOGIN_VIEW_ID;
} else {
redirectToViewId = GENERIC_ERROR_VIEW_ID;
}
} catch (Throwable e) {
// might be the case when session context is null
log.error(e);
redirectToViewId = UNTHEMED_ERROR_VIEW_ID;
}
if (redirectToErrorPage(redirectToViewId)) {
return null;
} else {
log.info("Unable to handle exception in web-context. "
+ "It might be an external (soap) request. "
+ "Throwing further...");
log.error("Original error", t);
throw cException;
}
}
}
private boolean redirectToErrorPage(String viewId) {
final String logPrefix = "<redirectToErrorPage> ";
final FacesContext facesContext = FacesContext.getCurrentInstance();
// we cannot call redirect if facesContext is null (Seam internals)
if (facesContext == null) {
// TODO decrease debug level
log.info(logPrefix + "cannot redirect to error page");
return false;
}
HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
// avoid further redirection
request.setAttribute(NXAuthConstants.DISABLE_REDIRECT_REQUEST_KEY,
Boolean.TRUE);
Redirect.instance().setViewId(viewId);
Redirect.instance().execute();
return true;
}
}