annis.gui.ReportBugWindow.java Source code

Java tutorial

Introduction

Here is the source code for annis.gui.ReportBugWindow.java

Source

/*
 * Copyright 2012 Corpuslinguistic working group Humboldt University Berlin.
 *
 * 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 annis.gui;

import annis.VersionInfo;
import annis.libgui.Helper;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.fieldgroup.PropertyId;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.validator.EmailValidator;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.Page;
import com.vaadin.server.StreamResource;
import com.vaadin.server.UserError;
import com.vaadin.server.VaadinService;
import com.vaadin.shared.Version;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Field;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Image;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.BaseTheme;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import javax.activation.FileDataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.ByteArrayDataSource;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.MultiPartEmail;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Thomas Krause <krauseto@hu-berlin.de>
 */
public class ReportBugWindow extends Window {

    private static final org.slf4j.Logger log = LoggerFactory.getLogger(MetaDataPanel.class);

    private FieldGroup form;

    private Button btSubmit;
    private Button btCancel;
    private Throwable cause;

    public ReportBugWindow(final String bugEMailAddress, final byte[] screenImage, final String imageMimeType,
            Throwable cause) {
        this.cause = cause;

        setSizeUndefined();
        setCaption("Report Problem");

        ReportFormLayout layout = new ReportFormLayout();
        setContent(layout);

        layout.setWidth("100%");
        layout.setHeight("-1px");

        setHeight("420px");
        setWidth("750px");

        form = new FieldGroup(new BeanItem<>(new BugReport()));
        form.bindMemberFields(layout);
        form.setBuffered(true);

        final ReportBugWindow finalThis = this;
        btSubmit = new Button("Submit problem report", new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                try {
                    form.commit();

                    if (sendBugReport(bugEMailAddress, screenImage, imageMimeType)) {
                        Notification.show("Problem report was sent",
                                "We will answer your problem report as soon as possible",
                                Notification.Type.HUMANIZED_MESSAGE);
                    }

                    UI.getCurrent().removeWindow(finalThis);

                } catch (FieldGroup.CommitException ex) {
                    List<String> errorFields = new LinkedList<>();
                    for (Field f : form.getFields()) {
                        if (f instanceof AbstractComponent) {
                            AbstractComponent c = (AbstractComponent) f;
                            if (f.isValid()) {
                                c.setComponentError(null);
                            } else {
                                errorFields.add(f.getCaption());
                                c.setComponentError(new UserError("Validation failed: "));
                            }
                        }
                    } // for each field
                    String message = "Please check the error messages "
                            + "(place mouse over red triangle) for the following fields:<br />";
                    message = message + StringUtils.join(errorFields, ",<br/>");
                    Notification notify = new Notification("Validation failed", message,
                            Notification.Type.WARNING_MESSAGE, true);
                    notify.show(UI.getCurrent().getPage());
                } catch (Exception ex) {
                    log.error("Could not send bug report", ex);
                    Notification.show("Could not send bug report", ex.getMessage(),
                            Notification.Type.WARNING_MESSAGE);
                }
            }
        });

        btCancel = new Button("Cancel", new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                form.discard();
                UI.getCurrent().removeWindow(finalThis);
            }
        });

        addScreenshotPreview(layout, screenImage, imageMimeType);

        HorizontalLayout buttons = new HorizontalLayout();
        buttons.addComponent(btSubmit);
        buttons.addComponent(btCancel);

        layout.addComponent(buttons);

    }

    private void addScreenshotPreview(Layout layout, final byte[] rawImage, String mimeType) {
        StreamResource res = new StreamResource(new ScreenDumpStreamSource(rawImage),
                "screendump_" + UUID.randomUUID().toString() + ".png");
        res.setMIMEType(mimeType);

        final Image imgScreenshot = new Image("Attached screenshot", res);
        imgScreenshot.setAlternateText(
                "Screenshot of the ANNIS browser window, " + "no other window or part of the desktop is captured.");
        imgScreenshot.setVisible(false);
        imgScreenshot.setWidth("100%");

        Button btShowScreenshot = new Button("Show attached screenshot",
                new ShowScreenshotClickListener(imgScreenshot));
        btShowScreenshot.addStyleName(BaseTheme.BUTTON_LINK);
        btShowScreenshot.setIcon(FontAwesome.PLUS_SQUARE_O);

        layout.addComponent(btShowScreenshot);
        layout.addComponent(imgScreenshot);
    }

    private boolean sendBugReport(String bugEMailAddress, byte[] screenImage, String imageMimeType) {
        MultiPartEmail mail = new MultiPartEmail();
        try {
            // server setup
            mail.setHostName("localhost");

            // content of the mail
            mail.addReplyTo(form.getField("email").getValue().toString(),
                    form.getField("name").getValue().toString());
            mail.setFrom(bugEMailAddress);
            mail.addTo(bugEMailAddress);

            mail.setSubject("[ANNIS BUG] " + form.getField("summary").getValue().toString());

            // TODO: add info about version etc.
            StringBuilder sbMsg = new StringBuilder();

            sbMsg.append("Reporter: ").append(form.getField("name").getValue().toString()).append(" (")
                    .append(form.getField("email").getValue().toString()).append(")\n");
            sbMsg.append("Version: ").append(VersionInfo.getVersion()).append("\n");
            sbMsg.append("Vaadin Version: ").append(Version.getFullVersion()).append("\n");
            sbMsg.append("Browser: ").append(Page.getCurrent().getWebBrowser().getBrowserApplication())
                    .append("\n");
            sbMsg.append("URL: ").append(UI.getCurrent().getPage().getLocation().toASCIIString()).append("\n");

            sbMsg.append("\n");

            sbMsg.append(form.getField("description").getValue().toString());
            mail.setMsg(sbMsg.toString());

            if (screenImage != null) {
                try {
                    mail.attach(new ByteArrayDataSource(screenImage, imageMimeType), "screendump.png",
                            "Screenshot of the browser content at time of problem report");
                } catch (IOException ex) {
                    log.error(null, ex);
                }
            }

            File logfile = new File(VaadinService.getCurrent().getBaseDirectory(), "/WEB-INF/log/annis-gui.log");
            if (logfile.exists() && logfile.isFile() && logfile.canRead()) {
                mail.attach(new FileDataSource(logfile), "annis-gui.log",
                        "Logfile of the GUI (shared by all users)");
            }

            if (cause != null) {
                try {
                    mail.attach(new ByteArrayDataSource(Helper.convertExceptionToMessage(cause), "text/plain"),
                            "exception.txt", "Exception that caused the user to report the problem");
                } catch (IOException ex) {
                    log.error(null, ex);
                }
            }

            mail.send();
            return true;

        } catch (EmailException ex) {
            Notification.show("E-Mail not configured on server",
                    "If this is no Kickstarter version please ask the administrator (" + bugEMailAddress
                            + ") of this ANNIS-instance for assistance. "
                            + "Problem reports are not available for ANNIS Kickstarter",
                    Notification.Type.ERROR_MESSAGE);
            log.error(null, ex);
            return false;
        }
    }

    public static class BugReport {
        private String summary = "";
        private String description = "What steps will reproduce the problem?\n" + "1.\n" + "2.\n" + "3.\n" + "\n"
                + "What is the expected result?\n" + "\n" + "\n" + "What happens instead\n" + "\n" + "\n"
                + "Please provide any additional information below.\n";
        private String name = "";
        private String email = "";

        public String getSummary() {
            return summary;
        }

        public void setSummary(String summary) {
            this.summary = summary;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String mail) {
            this.email = mail;
        }
    }

    public static class ReportFormLayout extends FormLayout {
        @PropertyId("summary")
        private TextField txtSummary;

        @PropertyId("description")
        private TextArea txtDescription;

        @PropertyId("name")
        private TextField txtName;

        @PropertyId("email")
        private TextField txtMail;

        public ReportFormLayout() {
            txtSummary = new TextField("Short Summary");
            txtSummary.setRequired(true);
            txtSummary.setRequiredError("You must provide a summary");
            txtSummary.setWidth("100%");

            txtDescription = new TextArea("Long Description");
            txtDescription.setRequired(true);
            txtDescription.setRequiredError("You must provide a description");
            txtDescription.setRows(10);
            txtDescription.setWidth("100%");

            txtName = new TextField("Your Name");
            txtName.setRequired(true);
            txtName.setRequiredError("You must provide your name");
            txtName.setWidth("100%");

            txtMail = new TextField("Your e-mail adress");
            txtMail.setRequired(true);
            txtMail.setRequiredError("You must provide a valid e-mail adress");
            txtMail.addValidator(new EmailValidator("You must provide a valid e-mail adress"));
            txtMail.setWidth("100%");

            addComponents(txtSummary, txtDescription, txtName, txtMail);

        }

    }

    private static class ScreenDumpStreamSource implements StreamResource.StreamSource {

        private final byte[] rawImage;

        public ScreenDumpStreamSource(byte[] rawImage) {
            this.rawImage = rawImage;
        }

        @Override
        public InputStream getStream() {
            return new ByteArrayInputStream(rawImage);
        }
    }

    private static class ShowScreenshotClickListener implements ClickListener {

        private final Image imgScreenshot;

        public ShowScreenshotClickListener(Image imgScreenshot) {
            this.imgScreenshot = imgScreenshot;
        }

        @Override
        public void buttonClick(ClickEvent event) {
            imgScreenshot.setVisible(!imgScreenshot.isVisible());
            if (imgScreenshot.isVisible()) {
                event.getButton().setCaption("Hide attached screenshot");
                event.getButton().setIcon(FontAwesome.MINUS_SQUARE_O);
            } else {
                event.getButton().setCaption("Show attached screenshot");
                event.getButton().setIcon(FontAwesome.PLUS_SQUARE_O);
            }
        }
    }

}