001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.main;
029
030import org.opencms.i18n.CmsEncoder;
031import org.opencms.i18n.CmsMessageContainer;
032import org.opencms.util.CmsStringUtil;
033
034import java.io.PrintWriter;
035import java.io.StringWriter;
036import java.util.Iterator;
037import java.util.Locale;
038
039/**
040 * Master exception type for all exceptions caused in OpenCms.<p>
041 *
042 * @since 6.0.0
043 */
044public class CmsException extends Exception implements I_CmsThrowable {
045
046    /** Serial version UID required for safe serialization. */
047    private static final long serialVersionUID = -1372556209321406104L;
048
049    /** The container for the localized message.  */
050    protected CmsMessageContainer m_message;
051
052    /**
053     * Creates a new localized Exception.<p>
054     *
055     * @param message the localized message container to use
056     */
057    public CmsException(CmsMessageContainer message) {
058
059        super(message.getKey());
060        m_message = message;
061    }
062
063    /**
064     * Creates a new localized Exception that also containers a root cause.<p>
065     *
066     * @param message the localized message container to use
067     * @param cause the Exception root cause
068     */
069    public CmsException(CmsMessageContainer message, Throwable cause) {
070
071        super(message.getKey(), cause);
072        m_message = message;
073    }
074
075    /**
076     * Returns the HTML formatted error stack of a Throwable.<p>
077     *
078     * The error stack is used by the common error screen
079     * that is displayed if an error occurs.<p>
080     *
081     * @param t the throwable to get the errorstack from
082     * @return the formatted value of the errorstack parameter
083     */
084    public static String getFormattedErrorstack(Throwable t) {
085
086        String stacktrace = CmsException.getStackTraceAsString(t);
087        if (CmsStringUtil.isEmpty(stacktrace)) {
088            return "";
089        } else {
090            stacktrace = CmsStringUtil.escapeJavaScript(stacktrace);
091            stacktrace = CmsEncoder.escapeXml(stacktrace);
092            StringBuffer result = new StringBuffer(256);
093            result.append(
094                "<html><body style='background-color: /*begin-color Window*/#ffffff/*end-color*/; overflow: scroll;'><pre>");
095            result.append(stacktrace);
096            result.append("</pre></body></html>");
097            return result.toString();
098        }
099    }
100
101    /**
102     * Returns the stack trace (including the message) of an exception as a String.<p>
103     *
104     * If the exception is a CmsException,
105     * also writes the root cause to the String.<p>
106     *
107     * @param e the exception to get the stack trace from
108     * @return the stack trace of an exception as a String
109     */
110    public static String getStackTraceAsString(Throwable e) {
111
112        StringWriter stringWriter = new StringWriter();
113        PrintWriter printWriter = new PrintWriter(stringWriter);
114        e.printStackTrace(printWriter);
115        if (e instanceof CmsMultiException) {
116            CmsMultiException me = (CmsMultiException)e;
117            Iterator<CmsException> it = me.getExceptions().iterator();
118            while (it.hasNext()) {
119                Throwable t = it.next();
120                t.printStackTrace(printWriter);
121            }
122        }
123        return stringWriter.toString();
124    }
125
126    /**
127     * Creates a copied instance of this localized exception.<p>
128     *
129     * @param container the message container
130     * @param cause the root cause
131     *
132     * @return a copied instance of this localized exception
133     */
134    public CmsException createException(CmsMessageContainer container, Throwable cause) {
135
136        return new CmsException(container, cause);
137    }
138
139    /**
140     * @see org.opencms.main.I_CmsThrowable#getLocalizedMessage()
141     */
142    @Override
143    public String getLocalizedMessage() {
144
145        if (m_message == null) {
146            return super.getLocalizedMessage();
147        }
148        return m_message.key();
149    }
150
151    /**
152     * @see org.opencms.main.I_CmsThrowable#getLocalizedMessage(Locale)
153     */
154    public String getLocalizedMessage(Locale locale) {
155
156        return m_message.key(locale);
157    }
158
159    /**
160     * @see java.lang.Throwable#getMessage()
161     */
162    @Override
163    public String getMessage() {
164
165        return getLocalizedMessage();
166    }
167
168    /**
169     * @see org.opencms.main.I_CmsThrowable#getMessageContainer()
170     */
171    public CmsMessageContainer getMessageContainer() {
172
173        return m_message;
174    }
175}