001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://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.ui.Button;
040import com.vaadin.ui.Button.ClickEvent;
041import com.vaadin.ui.Button.ClickListener;
042import com.vaadin.ui.CssLayout;
043import com.vaadin.ui.Window;
044import com.vaadin.ui.Window.CloseEvent;
045import com.vaadin.ui.Window.CloseListener;
046import com.vaadin.v7.shared.ui.label.ContentMode;
047import com.vaadin.v7.ui.Label;
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
097        m_onClose = onClose;
098        m_window = window;
099        CmsVaadinUtils.readAndLocalizeDesign(
100            this,
101            OpenCms.getWorkplaceManager().getMessages(A_CmsUI.get().getLocale()),
102            null);
103        m_icon.setContentMode(ContentMode.HTML);
104        m_icon.setValue(FontOpenCms.ERROR.getHtml());
105        m_errorLabel.setContentMode(ContentMode.PREFORMATTED);
106        final String labelId = "label" + new CmsUUID().toString();
107        String stacktrace = message + "\n\n" + ExceptionUtils.getStackTrace(t);
108        m_hiddenStack.setId(labelId);
109        m_hiddenStack.setValue(stacktrace);
110        m_errorLabel.setValue(stacktrace);
111        m_errorLabel.addStyleName(OpenCmsTheme.FULL_WIDTH_PADDING);
112        m_errorMessage.setContentMode(ContentMode.HTML);
113        m_errorMessage.setValue(message);
114
115        m_copyText.setSelector("#" + labelId);
116        m_details.setVisible(false);
117
118        m_okButton.addClickListener(new ClickListener() {
119
120            private static final long serialVersionUID = 1L;
121
122            public void buttonClick(ClickEvent event) {
123
124                onClose();
125            }
126        });
127        m_detailsButton.addClickListener(new ClickListener() {
128
129            private static final long serialVersionUID = 1L;
130
131            public void buttonClick(ClickEvent event) {
132
133                toggleDetails();
134            }
135        });
136        if (m_window != null) {
137            m_window.addCloseListener(new CloseListener() {
138
139                private static final long serialVersionUID = 1L;
140
141                public void windowClose(CloseEvent e) {
142
143                    onClose();
144                }
145            });
146        }
147
148    }
149
150    /**
151     * Shows the error dialog.<p>
152     *
153     * @param message the error message
154     * @param t the error to be displayed
155     */
156    public static void showErrorDialog(String message, Throwable t) {
157
158        showErrorDialog(message, t, null);
159    }
160
161    /**
162     * Shows the error dialog.<p>
163     *
164     * @param message the error message
165     * @param t the error to be displayed
166     * @param onClose executed on close
167     */
168    public static void showErrorDialog(String message, Throwable t, Runnable onClose) {
169
170        Window window = prepareWindow(DialogWidth.wide);
171        window.setCaption(Messages.get().getBundle(A_CmsUI.get().getLocale()).key(Messages.GUI_ERROR_0));
172        window.setContent(new CmsErrorDialog(message, t, onClose, window));
173        A_CmsUI.get().addWindow(window);
174    }
175
176    /**
177     * Shows the error dialog.<p>
178     *
179     * @param t the error to be displayed
180     */
181    public static void showErrorDialog(Throwable t) {
182
183        showErrorDialog(t.getLocalizedMessage(), t, null);
184    }
185
186    /**
187     * Shows the error dialog.<p>
188     *
189     * @param t the error to be displayed
190     * @param onClose executed on close
191     */
192    public static void showErrorDialog(Throwable t, Runnable onClose) {
193
194        showErrorDialog(t.getLocalizedMessage(), t, onClose);
195    }
196
197    /**
198     * Called on dialog close.<p>
199     */
200    void onClose() {
201
202        if (m_onClose != null) {
203            m_onClose.run();
204        }
205        if (m_window != null) {
206            m_window.close();
207        }
208    }
209
210    /**
211     * Toggles the details visibility.<p>
212     */
213    void toggleDetails() {
214
215        m_details.setVisible(!m_details.isVisible());
216        if (m_window != null) {
217            m_window.center();
218        }
219    }
220
221}