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