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, 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.ui.components;
029
030import org.opencms.main.OpenCms;
031import org.opencms.ui.A_CmsUI;
032import org.opencms.ui.CmsVaadinUtils;
033import org.opencms.ui.FontOpenCms;
034import org.opencms.ui.Messages;
035import org.opencms.util.CmsUUID;
036
037import org.apache.commons.lang3.exception.ExceptionUtils;
038
039import com.vaadin.v7.shared.ui.label.ContentMode;
040import com.vaadin.ui.Button;
041import com.vaadin.ui.Button.ClickEvent;
042import com.vaadin.ui.Button.ClickListener;
043import com.vaadin.ui.CssLayout;
044import com.vaadin.v7.ui.Label;
045import com.vaadin.ui.Window;
046import com.vaadin.ui.Window.CloseEvent;
047import com.vaadin.ui.Window.CloseListener;
048
049/**
050 * Dialog used to display error stack traces in the workplace.<p>
051 */
052public class CmsErrorDialog extends CmsBasicDialog {
053
054    /** Serial version id. */
055    private static final long serialVersionUID = 1L;
056
057    /** Label to display. */
058    private Label m_errorLabel;
059
060    /** Error message label. */
061    private Label m_errorMessage;
062
063    /** Warning icon. */
064    private Label m_icon;
065
066    /** Hidden stack trace element. */
067    private Label m_hiddenStack;
068
069    /** The OK button. */
070    private Button m_okButton;
071
072    /** The dialog context. */
073    private Runnable m_onClose;
074
075    /** The dialog window. */
076    private Window m_window;
077
078    /** The details component. */
079    private CssLayout m_details;
080
081    /** The select text button. */
082    private CmsCopyToClipboardButton m_copyText;
083
084    /** The toggle details button. */
085    private Button m_detailsButton;
086
087    /**
088     * Creates a new instance.<p>
089     *
090     * @param message the error message
091     * @param t the error to be displayed
092     * @param onClose executed on close
093     * @param window the dialog window if available
094     */
095    public CmsErrorDialog(String message, Throwable t, Runnable onClose, final Window window) {
096        m_onClose = onClose;
097        m_window = window;
098        CmsVaadinUtils.readAndLocalizeDesign(
099            this,
100            OpenCms.getWorkplaceManager().getMessages(A_CmsUI.get().getLocale()),
101            null);
102        m_icon.setContentMode(ContentMode.HTML);
103        m_icon.setValue(FontOpenCms.ERROR.getHtml());
104        m_errorLabel.setContentMode(ContentMode.PREFORMATTED);
105        final String labelId = "label" + new CmsUUID().toString();
106        String stacktrace = message + "\n\n" + ExceptionUtils.getStackTrace(t);
107        m_hiddenStack.setId(labelId);
108        m_hiddenStack.setValue(stacktrace);
109        m_errorLabel.setValue(stacktrace);
110        m_errorLabel.addStyleName(OpenCmsTheme.FULL_WIDTH_PADDING);
111        m_errorMessage.setContentMode(ContentMode.HTML);
112        m_errorMessage.setValue(message);
113
114        m_copyText.setSelector("#" + labelId);
115        m_details.setVisible(false);
116
117        m_okButton.addClickListener(new ClickListener() {
118
119            private static final long serialVersionUID = 1L;
120
121            public void buttonClick(ClickEvent event) {
122
123                onClose();
124            }
125        });
126        m_detailsButton.addClickListener(new ClickListener() {
127
128            private static final long serialVersionUID = 1L;
129
130            public void buttonClick(ClickEvent event) {
131
132                toggleDetails();
133            }
134        });
135        if (m_window != null) {
136            m_window.addCloseListener(new CloseListener() {
137
138                private static final long serialVersionUID = 1L;
139
140                public void windowClose(CloseEvent e) {
141
142                    onClose();
143                }
144            });
145        }
146
147    }
148
149    /**
150     * Shows the error dialog.<p>
151     *
152     * @param message the error message
153     * @param t the error to be displayed
154     */
155    public static void showErrorDialog(String message, Throwable t) {
156
157        showErrorDialog(message, t, null);
158    }
159
160    /**
161     * Shows the error dialog.<p>
162     *
163     * @param message the error message
164     * @param t the error to be displayed
165     * @param onClose executed on close
166     */
167    public static void showErrorDialog(String message, Throwable t, Runnable onClose) {
168
169        Window window = prepareWindow(DialogWidth.wide);
170        window.setCaption(Messages.get().getBundle(A_CmsUI.get().getLocale()).key(Messages.GUI_ERROR_0));
171        window.setContent(new CmsErrorDialog(message, t, onClose, window));
172        A_CmsUI.get().addWindow(window);
173    }
174
175    /**
176     * Shows the error dialog.<p>
177     *
178     * @param t the error to be displayed
179     */
180    public static void showErrorDialog(Throwable t) {
181
182        showErrorDialog(t.getLocalizedMessage(), t, null);
183    }
184
185    /**
186     * Shows the error dialog.<p>
187     *
188     * @param t the error to be displayed
189     * @param onClose executed on close
190     */
191    public static void showErrorDialog(Throwable t, Runnable onClose) {
192
193        showErrorDialog(t.getLocalizedMessage(), t, onClose);
194    }
195
196    /**
197     * Called on dialog close.<p>
198     */
199    void onClose() {
200
201        if (m_onClose != null) {
202            m_onClose.run();
203        }
204        if (m_window != null) {
205            m_window.close();
206        }
207    }
208
209    /**
210     * Toggles the details visibility.<p>
211     */
212    void toggleDetails() {
213
214        m_details.setVisible(!m_details.isVisible());
215        if (m_window != null) {
216            m_window.center();
217        }
218    }
219
220}