Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.primefaces.application.exceptionhandler.PrimeExceptionHandler Maven / Gradle / Ivy
/*
* Copyright 2009-2014 PrimeTek.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.primefaces.application.exceptionhandler;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.application.ProjectStage;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialResponseWriter;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.PhaseId;
import javax.faces.view.ViewDeclarationLanguage;
import org.primefaces.component.ajaxexceptionhandler.AjaxExceptionHandler;
import org.primefaces.component.ajaxexceptionhandler.AjaxExceptionHandlerVisitCallback;
import org.primefaces.context.RequestContext;
import org.primefaces.expression.SearchExpressionFacade;
import org.primefaces.util.ComponentUtils;
public class PrimeExceptionHandler extends ExceptionHandlerWrapper {
private static final Logger LOG = Logger.getLogger(PrimeExceptionHandler.class.getName());
private static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss";
private final ExceptionHandler wrapped;
public PrimeExceptionHandler(ExceptionHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ExceptionHandler getWrapped() {
return wrapped;
}
@Override
public void handle() throws FacesException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getResponseComplete()) {
return;
}
Iterable exceptionQueuedEvents = getUnhandledExceptionQueuedEvents();
if (exceptionQueuedEvents != null && exceptionQueuedEvents.iterator() != null) {
Iterator unhandledExceptionQueuedEvents = getUnhandledExceptionQueuedEvents().iterator();
if (unhandledExceptionQueuedEvents.hasNext()) {
try {
Throwable throwable = unhandledExceptionQueuedEvents.next().getContext().getException();
if (throwable instanceof AbortProcessingException) {
return;
}
unhandledExceptionQueuedEvents.remove();
Throwable rootCause = getRootCause(throwable);
ExceptionInfo info = createExceptionInfo(rootCause);
// print exception in development stage
if (context.getApplication().getProjectStage() == ProjectStage.Development) {
rootCause.printStackTrace();
}
// always log the exception
LOG.log(Level.SEVERE, rootCause.getMessage(), rootCause);
if (context.getPartialViewContext().isAjaxRequest()) {
handleAjaxException(context, rootCause, info);
} else {
handleRedirect(context, rootCause, info, false);
}
} catch (Exception ex) {
LOG.log(Level.SEVERE, "Could not handle exception!", ex);
}
}
while (unhandledExceptionQueuedEvents.hasNext()) {
// Any remaining unhandled exceptions are not interesting. First fix the first.
unhandledExceptionQueuedEvents.next();
unhandledExceptionQueuedEvents.remove();
}
}
}
@Override
public Throwable getRootCause(Throwable throwable) {
while ((ELException.class.isInstance(throwable) || FacesException.class.isInstance(throwable)) && throwable.getCause() != null) {
throwable = throwable.getCause();
}
return throwable;
}
protected void handleAjaxException(FacesContext context, Throwable rootCause, ExceptionInfo info) throws Exception {
ExternalContext externalContext = context.getExternalContext();
boolean responseResetted = false;
if (context.getCurrentPhaseId().equals(PhaseId.RENDER_RESPONSE)) {
if (!externalContext.isResponseCommitted()) {
String characterEncoding = externalContext.getResponseCharacterEncoding();
externalContext.responseReset();
externalContext.setResponseCharacterEncoding(characterEncoding);
responseResetted = true;
}
}
rootCause = buildView(context, rootCause, rootCause);
AjaxExceptionHandler handlerComponent = findHandlerComponent(context, rootCause);
context.getAttributes().put(ExceptionInfo.ATTRIBUTE_NAME, info);
// redirect if no UIAjaxExceptionHandler available
if (handlerComponent == null) {
handleRedirect(context, rootCause, info, responseResetted);
}
// handle custom update / onexception callback
else {
externalContext.addResponseHeader("Content-Type", "text/xml; charset=" + externalContext.getResponseCharacterEncoding());
externalContext.addResponseHeader("Cache-Control", "no-cache");
externalContext.setResponseContentType("text/xml");
PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
writer.startDocument();
writer.startElement("changes", null);
if (!ComponentUtils.isValueBlank(handlerComponent.getUpdate())) {
List updates = SearchExpressionFacade.resolveComponents(context, handlerComponent, handlerComponent.getUpdate());
if (updates != null && updates.size() > 0) {
context.setResponseWriter(writer);
for (int i = 0; i < updates.size(); i++) {
UIComponent component = updates.get(i);
writer.startElement("update", null);
writer.writeAttribute("id", component.getClientId(context), null);
writer.startCDATA();
component.encodeAll(context);
writer.endCDATA();
writer.endElement("update");
}
}
}
if (!ComponentUtils.isValueBlank(handlerComponent.getOnexception())) {
writer.startElement("eval", null);
writer.startCDATA();
writer.write("var hf=function(type,message,timestampp){");
writer.write(handlerComponent.getOnexception());
writer.write("};hf.call(this,\"" + info.getType() + "\",\"" + ComponentUtils.escapeText(info.getMessage()) + "\",\"" + info.getFormattedTimestamp() + "\");");
writer.endCDATA();
writer.endElement("eval");
}
writer.endElement("changes");
writer.endDocument();
context.responseComplete();
}
}
protected ExceptionInfo createExceptionInfo(Throwable rootCause) throws IOException {
ExceptionInfo info = new ExceptionInfo();
info.setException(rootCause);
info.setMessage(rootCause.getMessage());
info.setStackTrace(rootCause.getStackTrace());
info.setTimestamp(new Date());
info.setType(rootCause.getClass().getName());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
rootCause.printStackTrace(pw);
info.setFormattedStackTrace(sw.toString().replaceAll("(\r\n|\n)", " "));
pw.close();
sw.close();
SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT_PATTERN);
info.setFormattedTimestamp(format.format(info.getTimestamp()));
return info;
}
/**
* Finds the proper {@link AjaxExceptionHandler} for the given {@link Throwable}.
*
* @param context The {@link FacesContext}.
* @param throwable The occurred {@link Throwable}.
* @return The {@link UIAjaxExceptionHandler} or null
.
*/
protected AjaxExceptionHandler findHandlerComponent(FacesContext context, Throwable throwable) {
AjaxExceptionHandlerVisitCallback visitCallback = new AjaxExceptionHandlerVisitCallback(throwable);
context.getViewRoot().visitTree(VisitContext.createVisitContext(context), visitCallback);
return visitCallback.getHandler();
}
/**
* Builds the view if not already available.
* This is mostly required for ViewExpiredException's.
*
* @param context The {@link FacesContext}.
* @param throwable The occurred {@link Throwable}.
* @param rootCause The root cause.
* @return The unwrapped {@link Throwable}.
* @throws java.io.IOException If building the view fails.
*/
protected Throwable buildView(FacesContext context, Throwable throwable, Throwable rootCause) throws IOException
{
if (context.getViewRoot() == null) {
ViewHandler viewHandler = context.getApplication().getViewHandler();
String viewId = viewHandler.deriveViewId(context, calculateViewId(context));
ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(context, viewId);
UIViewRoot viewRoot = vdl.createView(context, viewId);
context.setViewRoot(viewRoot);
vdl.buildView(context, viewRoot);
// Workaround for Mojarra
// if UIViewRoot == null -> 'IllegalArgumentException' is throwed instead of 'ViewExpiredException'
if (rootCause == null && throwable instanceof IllegalArgumentException) {
rootCause = new javax.faces.application.ViewExpiredException(viewId);
}
}
return rootCause;
}
/**
* Calculates the current viewId - we can't get it from the ViewRoot if it's not available.
*
* @param context The {@link FacesContext}.
* @return The current viewId.
*/
protected String calculateViewId(FacesContext context) {
Map requestMap = context.getExternalContext().getRequestMap();
String viewId = (String) requestMap.get("javax.servlet.include.path_info");
if (viewId == null) {
viewId = context.getExternalContext().getRequestPathInfo();
}
if (viewId == null) {
viewId = (String) requestMap.get("javax.servlet.include.servlet_path");
}
if (viewId == null) {
viewId = context.getExternalContext().getRequestServletPath();
}
return viewId;
}
protected void handleRedirect(FacesContext context, Throwable rootCause, ExceptionInfo info, boolean responseResetted) throws IOException {
context.getExternalContext().getFlash().put(ExceptionInfo.ATTRIBUTE_NAME, info);
context.getExternalContext().getFlash().setRedirect(true);
Map errorPages = RequestContext.getCurrentInstance().getApplicationContext().getConfig().getErrorPages();
// get error page by exception type
String errorPage = errorPages.get(rootCause.getClass().getName());
// get default error page
if (errorPage == null) {
errorPage = errorPages.get(null);
}
if (errorPage == null) {
throw new IllegalArgumentException(
"No default error page (Status 500 or java.lang.Throwable) and no error page for type \"" + rootCause.getClass() + "\" defined!");
}
String url = context.getExternalContext().getRequestContextPath() + errorPage;
// workaround for mojarra -> mojarra doesn't reset PartialResponseWriter#inChanges if we call externalContext#resetResponse
if (responseResetted && context.getPartialViewContext().isAjaxRequest()) {
ExternalContext externalContext = context.getExternalContext();
PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
externalContext.addResponseHeader("Content-Type", "text/xml; charset=" + externalContext.getResponseCharacterEncoding());
externalContext.addResponseHeader("Cache-Control", "no-cache");
externalContext.setResponseContentType("text/xml");
writer.write("\n");
writer.startElement("partial-response", null);
writer.startElement("redirect", null);
writer.writeAttribute("url", url, null);
writer.endElement("redirect");
writer.endElement("partial-response");
}
else {
context.getExternalContext().redirect(url);
}
context.responseComplete();
}
}