io.hightide.handlers.ErrorHandler.java Source code

Java tutorial

Introduction

Here is the source code for io.hightide.handlers.ErrorHandler.java

Source

/*
 * Copyright (c) 2013. Ground Zero Labs, Private Company.
 *
 * 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 io.hightide.handlers;

import io.hightide.ApplicationContext;
import io.hightide.ApplicationStage;
import io.hightide.renderers.RythmHtmlRenderer;
import io.undertow.io.Sender;
import io.undertow.server.DefaultResponseListener;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.ResponseCodeHandler;
import io.undertow.util.Headers;
import io.undertow.util.StatusCodes;
import org.apache.commons.lang3.StringEscapeUtils;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;

import static java.util.Objects.nonNull;

/**
 * @author <a href="mailto:gpan@groundzerolabs.com">George Panagiotopoulos</a>
 */
public class ErrorHandler implements HttpHandler {

    private volatile HttpHandler next = ResponseCodeHandler.HANDLE_404;

    private boolean devMode = false;

    public ErrorHandler(HttpHandler next) {
        devMode = ApplicationStage.DEV.equals(ApplicationContext.instance().getAppStage());
        this.next = next;
    }

    public ErrorHandler(boolean devMode, HttpHandler next) {
        this(next);
        this.devMode = devMode;
    }

    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        exchange.addDefaultResponseListener(new DefaultResponseListener() {
            @Override
            public boolean handleDefaultResponse(final HttpServerExchange exchange) {
                if (!exchange.isResponseChannelAvailable()) {
                    return false;
                }
                if (exchange.getResponseCode() >= 400) {
                    Throwable t = exchange.getAttachment(HightideHandler.EXCEPTION_ATTACHMENT);
                    String exceptionString;
                    String message = exchange.getResponseCode() == 404 ? "Wrong address, no one lives here!"
                            : "Server's on fire, run for your life!";

                    String errorPage;
                    try {
                        Map<String, Object> errorMap = new HashMap<>();
                        errorMap.put("message", message);
                        errorMap.put("responseCode", exchange.getResponseCode());
                        errorMap.put("reason", StatusCodes.getReason(exchange.getResponseCode()));
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        t.printStackTrace(new PrintStream(baos));
                        exceptionString = baos.toString();
                        errorMap.put("exception", exceptionString);
                        errorMap.put("exceptionMsg", t.getMessage());
                        errorPage = new RythmHtmlRenderer().render("errors/default.html.rythm", errorMap);
                    } catch (Exception e) {
                        exceptionString = printException(t);
                        errorPage = "<html><head><title>Error</title></head><body>" + "<h1>" + message + "</h1>"
                                + exchange.getResponseCode() + " - "
                                + StatusCodes.getReason(exchange.getResponseCode()) + exceptionString
                                + "</body></html>";
                    }
                    exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, "" + errorPage.length());
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/html");
                    Sender sender = exchange.getResponseSender();
                    sender.send(errorPage);
                    return true;
                }
                return false;
            }
        });
        next.handleRequest(exchange);
    }

    private String printException(Throwable t) {
        StackTraceElement ste = t.getStackTrace().length > 0 ? t.getStackTrace()[0] : null;
        String message;
        if (nonNull(t.getMessage())) {
            message = htmlify(t.getMessage());
        } else {
            message = "";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("<div><strong>Error Message:</strong> ").append(t.getClass().getName()).append(" - ")
                .append(message).append("<br/><br/>");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        t.printStackTrace(new PrintStream(baos));
        sb.append("<strong>Stacktrace</strong><br/><div class='exception'>").append(htmlify(baos.toString()))
                .append("</div>");
        //sb.append("File name: ").append(ste.getFileName()).append(" at line ").append(ste.getLineNumber()).append(nl);
        //sb.append("Method Called: ").append(ste.getClassName()).append(".").append(ste.getMethodName());
        return sb.toString();
    }

    private String htmlify(String str) {
        return StringEscapeUtils.escapeHtml4(str).replaceAll("\\n", "<br/>").replaceAll("\\t",
                "&nbsp;&nbsp;&nbsp;&nbsp;");
    }
}