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 * Nuxeo - initial API and implementation 016 * 017 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.shield; 021 022import java.io.Serializable; 023import java.util.Map; 024 025import javax.faces.context.ExternalContext; 026import javax.faces.context.FacesContext; 027import javax.faces.event.PhaseId; 028import javax.interceptor.AroundInvoke; 029import javax.interceptor.InvocationContext; 030import javax.servlet.ServletRequest; 031import javax.servlet.http.HttpServletRequest; 032import javax.transaction.SystemException; 033 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.jboss.seam.contexts.Context; 037import org.jboss.seam.contexts.Contexts; 038import org.jboss.seam.contexts.FacesLifecycle; 039import org.jboss.seam.faces.Redirect; 040import org.jboss.seam.transaction.Transaction; 041import org.nuxeo.common.utils.ExceptionUtils; 042import org.nuxeo.ecm.core.api.DocumentSecurityException; 043import org.nuxeo.ecm.core.api.NuxeoException; 044import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants; 045import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper; 046 047/** 048 * Error handling interceptor. 049 * <p> 050 * Redirects to the good error page if an exception is caught: login page on security exception, themed error page on 051 * other exceptions and unthemed error page when another error is caught while rendering the error page. 052 * 053 * @author <a href="mailto:rcaraghin@nuxeo.com">Razvan Caraghin</a> 054 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 055 * @deprecated No need anymore, error is processed in NuxeoExceptionFilter 056 */ 057@Deprecated 058public class NuxeoErrorInterceptor implements Serializable { 059 060 private static final long serialVersionUID = 6519836435278721L; 061 062 private static final Log log = LogFactory.getLog(NuxeoErrorInterceptor.class); 063 064 private static final String GENERIC_ERROR_VIEW_ID = "/generic_error_page.xhtml"; 065 066 private static final String UNTHEMED_ERROR_VIEW_ID = "/unthemed_generic_error_page.xhtml"; 067 068 private static final String LOGIN_VIEW_ID = "/login.jsp"; 069 070 @AroundInvoke 071 public Object invokeAndWrapExceptions(InvocationContext invocation) throws SystemException, 072 DocumentSecurityException { 073 try { 074 // log.debug("Before invocation..."); 075 return invocation.proceed(); 076 } catch (Exception t) { // deals with interrupt below 077 ExceptionUtils.checkInterrupt(t); 078 079 if (Transaction.instance().isActive()) { 080 Transaction.instance().setRollbackOnly(); 081 } 082 083 FacesContext facesContext = FacesContext.getCurrentInstance(); 084 085 if (FacesLifecycle.getPhaseId() == PhaseId.RENDER_RESPONSE) { 086 if (ExceptionHelper.isSecurityError(t)) { 087 if (facesContext != null) { 088 Object req = facesContext.getExternalContext().getRequest(); 089 if (req instanceof ServletRequest) { 090 ServletRequest request = (ServletRequest) req; 091 request.setAttribute("securityException", t); 092 } 093 } 094 throw new DocumentSecurityException("Security Error during call of " 095 + invocation.getTarget().toString(), t); 096 } 097 } 098 099 NuxeoException cException = new NuxeoException(t); 100 // redirect is not allowed during render response phase => throw 101 // the error without redirecting 102 if (FacesLifecycle.getPhaseId() == PhaseId.RENDER_RESPONSE) { 103 if (facesContext != null) { 104 Object req = facesContext.getExternalContext().getRequest(); 105 if (req instanceof ServletRequest) { 106 ServletRequest request = (ServletRequest) req; 107 request.setAttribute("applicationException", cException); 108 } 109 } 110 throw cException; 111 } 112 113 // check if previous page was already an error page to avoid 114 // redirect cycle 115 if (facesContext != null) { 116 ExternalContext externalContext = facesContext.getExternalContext(); 117 if (externalContext != null) { 118 Map<String, String[]> requestMap = externalContext.getRequestHeaderValuesMap(); 119 if (requestMap != null) { 120 String[] previousPage = requestMap.get("Referer"); 121 if (previousPage != null && previousPage.length != 0) { 122 String pageName = previousPage[0]; 123 if (pageName != null && pageName.contains("error_page")) { 124 redirectToErrorPage(UNTHEMED_ERROR_VIEW_ID); 125 return null; 126 } 127 } 128 } 129 } 130 } 131 132 String redirectToViewId = null; 133 try { 134 log.error("Exception caught, redirecting to the error page...", cException); 135 final Context sessionContext = Contexts.getSessionContext(); 136 // set applicationException in session hoping 137 // ErrorPageActionListener will inject it 138 sessionContext.set("applicationException", cException); 139 if (ExceptionHelper.isSecurityError(t) || cException.getCause() instanceof DocumentSecurityException) { 140 redirectToViewId = LOGIN_VIEW_ID; 141 } else { 142 redirectToViewId = GENERIC_ERROR_VIEW_ID; 143 } 144 } catch (RuntimeException e) { 145 // might be the case when session context is null 146 log.error(e, e); 147 redirectToViewId = UNTHEMED_ERROR_VIEW_ID; 148 } 149 150 if (redirectToErrorPage(redirectToViewId)) { 151 return null; 152 } else { 153 log.info("Unable to handle exception in web-context. " + "It might be an external (soap) request. " 154 + "Throwing further..."); 155 log.error("Original error", t); 156 throw cException; 157 } 158 } 159 } 160 161 private boolean redirectToErrorPage(String viewId) { 162 final String logPrefix = "<redirectToErrorPage> "; 163 164 final FacesContext facesContext = FacesContext.getCurrentInstance(); 165 // we cannot call redirect if facesContext is null (Seam internals) 166 if (facesContext == null) { 167 // TODO decrease debug level 168 log.info(logPrefix + "cannot redirect to error page"); 169 return false; 170 } 171 172 HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest(); 173 // avoid further redirection 174 request.setAttribute(NXAuthConstants.DISABLE_REDIRECT_REQUEST_KEY, Boolean.TRUE); 175 176 Redirect.instance().setViewId(viewId); 177 Redirect.instance().execute(); 178 return true; 179 } 180 181}