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.
/*
* Copyright (C) 2014 the original author or authors.
*
* 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 ro.pippo.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.pippo.core.route.Route;
import ro.pippo.core.route.RouteContext;
import ro.pippo.core.util.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* DefaultErrorHandler is the core ExceptionHandler that integrates with
* the TemplateEngine & ContentTypeEngines. It generates a representation
* of an exception or error result.
*
* @author Decebal Suiu
* @author James Moger
*/
public class DefaultErrorHandler implements ErrorHandler {
private static final Logger log = LoggerFactory.getLogger(DefaultErrorHandler.class);
private static final String MESSAGE = "message";
private Application application;
private final Map, ExceptionHandler> exceptionHandlers;
public DefaultErrorHandler(Application application) {
this.application = application;
this.exceptionHandlers = new HashMap<>();
setExceptionHandler(StatusCodeException.class, new StatusCodeExceptionHandler(this));
}
@Override
public void setExceptionHandler(Class extends Exception> exceptionClass, ExceptionHandler exceptionHandler) {
exceptionHandlers.put(exceptionClass, exceptionHandler);
}
/**
* Returns an ExceptionHandler registered for this exception type.
* If no handler is found it returns null and the default handle
* (this class) is used.
*
* @param exception
* @return an exception handler or null
*/
@Override
public ExceptionHandler getExceptionHandler(Exception exception) {
Class extends Exception> exceptionClass = exception.getClass();
if (!exceptionHandlers.containsKey(exceptionClass)) {
Class> superClass = exceptionClass.getSuperclass();
while (superClass != null) {
if (exceptionHandlers.containsKey(superClass)) {
ExceptionHandler exceptionHandler = exceptionHandlers.get(superClass);
exceptionHandlers.put(exceptionClass, exceptionHandler);
return exceptionHandler;
}
superClass = superClass.getSuperclass();
}
// avoid superclass traversal in the future if we didn't find a handler
exceptionHandlers.put(exceptionClass, null);
}
return exceptionHandlers.get(exceptionClass);
}
@Override
public void handle(int statusCode, RouteContext routeContext) {
checkForRecursion(routeContext);
routeContext.status(statusCode);
// start with the content type specified for the response
String contentType = routeContext.getResponse().getContentType();
if (StringUtils.isNullOrEmpty(contentType)) {
if (!StringUtils.isNullOrEmpty(routeContext.getRequest().getAcceptType())) {
String acceptType = routeContext.getRequest().getAcceptType();
if (acceptType.startsWith(HttpConstants.ContentType.TEXT_HTML)
|| acceptType.startsWith(HttpConstants.ContentType.TEXT_XHTML)) {
// exception during a browser request
contentType = HttpConstants.ContentType.TEXT_HTML;
}
}
if (StringUtils.isNullOrEmpty(contentType)) {
// unspecified so negotiate a content type based on the request
routeContext.negotiateContentType();
// retrieve the negotiated type
contentType = routeContext.getResponse().getContentType();
}
}
if (StringUtils.isNullOrEmpty(contentType)) {
log.debug("No accept type nor content type specified! Defaulting to text/html.");
renderHtml(statusCode, routeContext);
} else if (contentType.equals(HttpConstants.ContentType.TEXT_HTML)) {
// render an html page
renderHtml(statusCode, routeContext);
} else {
// render an object representation
ContentTypeEngine engine = application.getContentTypeEngine(contentType);
if (engine == null) {
log.warn("No registered content type engine for '{}'", contentType);
renderHtml(statusCode, routeContext);
} else {
Error error = prepareError(statusCode, routeContext);
try {
routeContext.getResponse().contentType(engine.getContentType()).send(error);
} catch (Exception e) {
log.error("Unexpected error generating '{}' as '{}'!", Error.class.getName(), contentType, e);
routeContext.status(HttpConstants.StatusCode.INTERNAL_ERROR);
routeContext.send(application.getMessages().get("pippo.statusCode500", routeContext));
}
}
}
}
protected void renderHtml(int statusCode, RouteContext routeContext) {
if (application.getTemplateEngine() == null) {
renderDirectly(statusCode, routeContext);
} else {
String template = getTemplateForStatusCode(statusCode);
if (template == null) {
log.debug("There is no {} template for status code '{}'", application.getTemplateEngine().getClass()
.getSimpleName(), statusCode);
renderDirectly(statusCode, routeContext);
} else {
try {
Error error = prepareError(statusCode, routeContext);
Map bindings = error.asMap();
bindings.putAll(prepareTemplateBindings(statusCode, routeContext));
routeContext.setLocals(bindings);
routeContext.render(template);
} catch (Exception e) {
log.error("Unexpected error rendering your '{}' template!", template, e);
handle(e, routeContext);
}
}
}
}
@Override
public void handle(Exception exception, RouteContext routeContext) {
checkForRecursion(routeContext);
ExceptionHandler exceptionHandler = getExceptionHandler(exception);
if (exceptionHandler != null) {
log.debug("Handling '{}' with '{}'", exception.getClass().getSimpleName(), exceptionHandler.getClass().getName());
exceptionHandler.handle(exception, routeContext);
return;
}
log.error(exception.getMessage(), exception);
if (routeContext.getResponse().isCommitted()) {
log.debug("The response has already been committed. Cannot use the exception handler.");
return;
}
String message = exception.getMessage();
if (!StringUtils.isNullOrEmpty(message) && !routeContext.getResponse().getLocals().containsKey(MESSAGE)) {
routeContext.setLocal(MESSAGE, message);
}
if (application.getPippoSettings().isDev()) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
exception.printStackTrace(printWriter);
String stackTrace = stringWriter.toString();
routeContext.setLocal("stacktrace", stackTrace);
}
handle(HttpConstants.StatusCode.INTERNAL_ERROR, routeContext);
}
/**
* Render the result directly.
*
* @param routeContext
*/
protected void renderDirectly(int statusCode, RouteContext routeContext) {
if (statusCode == HttpConstants.StatusCode.NOT_FOUND && !application.getPippoSettings().isProd()) {
StringBuilder content = new StringBuilder();
content.append("");
content.append("
");
content.append("Cannot find a route for '");
content.append(routeContext.getRequestMethod());
content.append(" ");
content.append(routeContext.getRequestUri());
content.append("'
");
content.append("
Available routes:
");
content.append("
");
List routes = application.getRouter().getRoutes();
for (Route route : routes) {
content.append("