/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* 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 com.intellij.diagnostic;
import com.intellij.errorreport.ErrorReportSender;
import com.intellij.errorreport.bean.ErrorBean;
import com.intellij.errorreport.error.AuthorizationFailedException;
import com.intellij.errorreport.error.UpdateAvailableException;
import com.intellij.errorreport.error.WebServiceException;
import com.intellij.ide.DataManager;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.idea.ActionsBundle;
import com.intellij.idea.IdeaLogger;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationAction;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.CheckForUpdateAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import com.intellij.xml.util.XmlStringUtil;
import consulo.ide.updateSettings.UpdateSettings;
import consulo.ide.webService.WebServiceApi;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.Set;
/**
* @author max
*/
public class ITNReporter extends ErrorReportSubmitter {
public static final ITNReporter ourInternalInstance = new ITNReporter();
private static String ourPreviousErrorReporterId;
@Override
public boolean trySubmitAsync(IdeaLoggingEvent[] events, String additionalInfo, Component parentComponent, Consumer<SubmittedReportInfo> consumer) {
return sendError(events[0], additionalInfo, parentComponent, consumer);
}
/**
* @noinspection ThrowablePrintStackTrace
*/
private static boolean sendError(IdeaLoggingEvent event,
String additionalInfo,
final Component parentComponent,
final Consumer<SubmittedReportInfo> callback) {
ErrorBean errorBean = new ErrorBean(event.getThrowable(), IdeaLogger.ourLastActionId);
return doSubmit(event, parentComponent, callback, errorBean, additionalInfo);
}
private static boolean doSubmit(final IdeaLoggingEvent event,
final Component parentComponent,
final Consumer<SubmittedReportInfo> callback,
final ErrorBean errorBean,
final String description) {
final DataContext dataContext = DataManager.getInstance().getDataContext(parentComponent);
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
errorBean.setDescription(description);
errorBean.setMessage(event.getMessage());
if (ourPreviousErrorReporterId != null) {
errorBean.setPreviousException(ourPreviousErrorReporterId);
}
Throwable t = event.getThrowable();
if (t != null) {
Set<PluginId> pluginIds = IdeErrorsDialog.findPluginIds(t);
for (PluginId pluginId : pluginIds) {
final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(pluginId);
if (pluginDescriptor != null) {
errorBean.addAffectedPlugin(pluginId, StringUtil.notNullize(pluginDescriptor.getVersion(), "?"));
}
}
}
Object data = event.getData();
if (data instanceof AbstractMessage) {
errorBean.setAssigneeId(((AbstractMessage)data).getAssigneeId());
}
if (data instanceof LogMessageEx) {
errorBean.setAttachments(((LogMessageEx)data).getAttachments());
}
ErrorReportSender.sendReport(project, errorBean, id -> {
ourPreviousErrorReporterId = id;
String shortId = id.substring(0, 8);
final SubmittedReportInfo reportInfo = new SubmittedReportInfo(WebServiceApi.ERROR_REPORT.buildUrl("#" + id), shortId, SubmittedReportInfo.SubmissionStatus.NEW_ISSUE);
callback.consume(reportInfo);
ApplicationManager.getApplication().invokeLater(() -> {
StringBuilder text = new StringBuilder();
final String url = IdeErrorsDialog.getUrl(reportInfo);
IdeErrorsDialog.appendSubmissionInformation(reportInfo, text, url);
text.append(".");
if (reportInfo.getStatus() != SubmittedReportInfo.SubmissionStatus.FAILED) {
text.append("<br/>").append(DiagnosticBundle.message("error.report.gratitude"));
}
NotificationType type = reportInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.FAILED ? NotificationType.ERROR : NotificationType.INFORMATION;
NotificationListener listener = url != null ? new NotificationListener.UrlOpeningListener(true) : null;
ReportMessages.GROUP.createNotification(ReportMessages.ERROR_REPORT, XmlStringUtil.wrapInHtml(text), type, listener).setImportant(false)
.notify(project);
});
}, e -> ApplicationManager.getApplication().invokeLater(() -> {
String msg;
if (e instanceof AuthorizationFailedException) {
msg = DiagnosticBundle.message("error.report.authentication.failed");
}
else if (e instanceof WebServiceException) {
msg = DiagnosticBundle.message("error.report.posting.failed", e.getMessage());
}
else {
msg = DiagnosticBundle.message("error.report.sending.failure");
}
if (e instanceof UpdateAvailableException) {
callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
Notification notification =
ReportMessages.GROUP.createNotification(DiagnosticBundle.message("error.report.update.required.message"), NotificationType.INFORMATION);
notification.setTitle(ReportMessages.ERROR_REPORT);
notification.setImportant(false);
notification.addAction(new NotificationAction(ActionsBundle.actionText("CheckForUpdate")) {
@Override
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
CheckForUpdateAction.actionPerformed(e.getData(CommonDataKeys.PROJECT), UpdateSettings.getInstance());
}
});
notification.notify(project);
}
else if (showYesNoDialog(parentComponent, project, msg, ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) {
callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
}
else {
if (e instanceof AuthorizationFailedException) {
// TODO [VISTALL]
}
ApplicationManager.getApplication().invokeLater(() -> doSubmit(event, parentComponent, callback, errorBean, description));
}
}));
return true;
}
private static void showMessageDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
Messages.showMessageDialog(parentComponent, message, title, icon);
}
else {
Messages.showMessageDialog(project, message, title, icon);
}
}
private static int showYesNoDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
return Messages.showYesNoDialog(parentComponent, message, title, icon);
}
else {
return Messages.showYesNoDialog(project, message, title, icon);
}
}
}