org.apache.wicket.markup.html.pages.ExceptionErrorPage.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.markup.html.pages.ExceptionErrorPage.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.wicket.markup.html.pages;

import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.wicket.Page;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.MarkupException;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.basic.MultiLineLabel;
import org.apache.wicket.markup.html.debug.PageView;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.util.lang.Generics;

/**
 * Shows a runtime exception on a nice HTML page.
 * 
 * @author Jonathan Locke
 */
public class ExceptionErrorPage extends AbstractErrorPage {
    private static final long serialVersionUID = 1L;

    /** Keep a reference to the root cause. WicketTester will use it */
    private final transient Throwable throwable;

    /**
     * Constructor.
     * 
     * @param throwable
     *            The exception to show
     * @param page
     *            The page being rendered when the exception was thrown
     */
    public ExceptionErrorPage(final Throwable throwable, final Page page) {
        this.throwable = throwable;

        // Add exception label
        add(new MultiLineLabel("exception", getErrorMessage(throwable)));

        add(new MultiLineLabel("stacktrace", getStackTrace(throwable)));

        // Get values
        String resource = "";
        String markup = "";
        MarkupStream markupStream = null;

        if (throwable instanceof MarkupException) {
            markupStream = ((MarkupException) throwable).getMarkupStream();

            if (markupStream != null) {
                markup = markupStream.toHtmlDebugString();
                resource = markupStream.getResource().toString();
            }
        }

        // Create markup label
        final MultiLineLabel markupLabel = new MultiLineLabel("markup", markup);

        markupLabel.setEscapeModelStrings(false);

        // Add container with markup highlighted
        final WebMarkupContainer markupHighlight = new WebMarkupContainer("markupHighlight");

        markupHighlight.add(markupLabel);
        markupHighlight.add(new Label("resource", resource));
        add(markupHighlight);

        // Show container if markup stream is available
        markupHighlight.setVisible(markupStream != null);

        add(new Link<Void>("displayPageViewLink") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick() {
                ExceptionErrorPage.this.replace(new PageView("componentTree", page));
                setVisible(false);
            }
        });

        add(new Label("componentTree", ""));
    }

    /**
     * Converts a Throwable to a string.
     * 
     * @param throwable
     *            The throwable
     * @return The string
     */
    public String getErrorMessage(final Throwable throwable) {
        if (throwable != null) {
            StringBuilder sb = new StringBuilder(256);

            // first print the last cause
            List<Throwable> al = convertToList(throwable);
            int length = al.size() - 1;
            Throwable cause = al.get(length);
            sb.append("Last cause: ").append(cause.getMessage()).append('\n');
            if (throwable instanceof WicketRuntimeException) {
                String msg = throwable.getMessage();
                if ((msg != null) && (msg.equals(cause.getMessage()) == false)) {
                    if (throwable instanceof MarkupException) {
                        MarkupStream stream = ((MarkupException) throwable).getMarkupStream();
                        if (stream != null) {
                            String text = "\n" + stream.toString();
                            if (msg.endsWith(text)) {
                                msg = msg.substring(0, msg.length() - text.length());
                            }
                        }
                    }

                    sb.append("WicketMessage: ");
                    sb.append(msg);
                    sb.append("\n\n");
                }
            }
            return sb.toString();
        } else {
            return "[Unknown]";
        }
    }

    /**
     * Converts a Throwable to a string.
     * 
     * @param throwable
     *            The throwable
     * @return The string
     */
    public String getStackTrace(final Throwable throwable) {
        if (throwable != null) {
            List<Throwable> al = convertToList(throwable);

            StringBuilder sb = new StringBuilder(256);

            // first print the last cause
            int length = al.size() - 1;
            Throwable cause = al.get(length);

            sb.append("Root cause:\n\n");
            outputThrowable(cause, sb, false);

            if (length > 0) {
                sb.append("\n\nComplete stack:\n\n");
                for (int i = 0; i < length; i++) {
                    outputThrowable(al.get(i), sb, true);
                    sb.append("\n");
                }
            }
            return sb.toString();
        } else {
            return "<Null Throwable>";
        }
    }

    /**
     * @param throwable
     * @return xxx
     */
    private List<Throwable> convertToList(final Throwable throwable) {
        List<Throwable> al = Generics.newArrayList();
        Throwable cause = throwable;
        al.add(cause);
        while ((cause.getCause() != null) && (cause != cause.getCause())) {
            cause = cause.getCause();
            al.add(cause);
        }
        return al;
    }

    /**
     * Outputs the throwable and its stacktrace to the stringbuffer. If stopAtWicketSerlvet is true
     * then the output will stop when the org.apache.wicket servlet is reached. sun.reflect.
     * packages are filtered out.
     * 
     * @param cause
     * @param sb
     * @param stopAtWicketServlet
     */
    private void outputThrowable(Throwable cause, StringBuilder sb, boolean stopAtWicketServlet) {
        sb.append(cause);
        sb.append("\n");
        StackTraceElement[] trace = cause.getStackTrace();
        for (int i = 0; i < trace.length; i++) {
            String traceString = trace[i].toString();
            if (!(traceString.startsWith("sun.reflect.") && i > 1)) {
                sb.append("     at ");
                sb.append(traceString);
                sb.append("\n");
                if (stopAtWicketServlet && (traceString.startsWith("org.apache.wicket.protocol.http.WicketServlet")
                        || traceString.startsWith("org.apache.wicket.protocol.http.WicketFilter"))) {
                    return;
                }
            }
        }
    }

    @Override
    protected void setHeaders(final WebResponse response) {
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }

    /**
     * Get access to the exception
     * 
     * @return The exception
     */
    public Throwable getThrowable() {
        return throwable;
    }
}