refactor errorhandler

This commit is contained in:
yugecin
2017-05-27 01:46:50 +02:00
parent a5efe7e649
commit 08f5bfc27f
23 changed files with 191 additions and 209 deletions

View File

@@ -22,13 +22,13 @@ import itdelatrisu.opsu.beatmap.BeatmapWatchService;
import itdelatrisu.opsu.db.DBController;
import itdelatrisu.opsu.downloads.DownloadList;
import org.newdawn.slick.util.Log;
import yugecin.opsudance.core.errorhandling.ErrorHandler;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import static yugecin.opsudance.core.errorhandling.ErrorHandler.*;
import static yugecin.opsudance.core.Entrypoint.sout;
import static yugecin.opsudance.core.InstanceContainer.*;
import static yugecin.opsudance.options.Options.*;
@@ -75,7 +75,7 @@ public class OpsuDance {
displayContainer.setup();
displayContainer.resume();
} catch (Exception e) {
ErrorHandler.error("could not initialize GL", e).allowTerminate().preventContinue().show();
explode("could not initialize GL", e, ALLOW_TERMINATE | PREVENT_CONTINUE);
return false;
}
Exception caughtException = null;
@@ -86,12 +86,12 @@ public class OpsuDance {
}
displayContainer.teardown();
displayContainer.pause();
return caughtException != null && ErrorHandler.error("update/render error", caughtException).allowTerminate().show().shouldIgnoreAndContinue();
return caughtException != null && explode("update/render error", caughtException, ALLOW_TERMINATE);
}
private void initDatabase() {
try {
DBController.init(config);
DBController.init();
} catch (UnsatisfiedLinkError e) {
errorAndExit("Could not initialize database.", e);
}
@@ -146,13 +146,8 @@ public class OpsuDance {
}
}
private void errorAndExit(String errstr) {
ErrorHandler.error(errstr, new Throwable()).allowTerminate().preventContinue().show();
System.exit(1);
}
private void errorAndExit(String errstr, Throwable cause) {
ErrorHandler.error(errstr, cause).preventContinue().show();
explode(errstr, cause, PREVENT_CONTINUE);
System.exit(1);
}

View File

@@ -466,6 +466,10 @@ public class DisplayContainer implements ErrorDumpable, ResolutionChangedListene
public void writeErrorDump(StringWriter dump) {
dump.append("> DisplayContainer dump\n");
dump.append("OpenGL version: ").append(glVersion).append( "(").append(glVendor).append(")\n");
if (state == null) {
dump.append("state is null!\n");
return;
}
state.writeErrorDump(dump);
}

View File

@@ -20,8 +20,6 @@ package yugecin.opsudance.core.errorhandling;
import itdelatrisu.opsu.Utils;
import org.newdawn.slick.util.Log;
import yugecin.opsudance.core.Constants;
import yugecin.opsudance.core.DisplayContainer;
import yugecin.opsudance.options.Configuration;
import yugecin.opsudance.utils.MiscUtils;
import javax.swing.*;
@@ -36,80 +34,52 @@ import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import static yugecin.opsudance.core.InstanceContainer.*;
/**
* based on itdelatrisu.opsu.ErrorHandler
*/
public class ErrorHandler {
private static ErrorHandler instance;
private final Configuration config;
private final DisplayContainer displayContainer;
private String customMessage;
private Throwable cause;
private String errorDump;
private String messageBody;
private boolean preventContinue;
private boolean preventReport;
private boolean ignoreAndContinue;
private boolean allowTerminate;
public ErrorHandler(DisplayContainer displayContainer, Configuration config) {
this.displayContainer = displayContainer;
this.config = config;
instance = this;
}
private ErrorHandler init(String customMessage, Throwable cause) {
this.customMessage = customMessage;
this.cause = cause;
public final static int DEFAULT_OPTIONS = 0;
public final static int PREVENT_CONTINUE = 1;
public final static int PREVENT_REPORT = 2;
public final static int ALLOW_TERMINATE = 4;
public static boolean explode(String customMessage, Throwable cause, int flags) {
StringWriter dump = new StringWriter();
try {
displayContainer.writeErrorDump(dump);
} catch (Exception e) {
dump
.append("### ")
.append(e.getClass().getSimpleName())
.append(" while creating errordump");
e.printStackTrace(new PrintWriter(dump));
if (displayContainer == null) {
dump.append("displayContainer is null!\n");
} else {
try {
displayContainer.writeErrorDump(dump);
} catch (Exception e) {
dump
.append("### ")
.append(e.getClass().getSimpleName())
.append(" while creating errordump");
e.printStackTrace(new PrintWriter(dump));
}
}
errorDump = dump.toString();
String errorDump = dump.toString();
dump = new StringWriter();
dump.append(customMessage).append("\n");
cause.printStackTrace(new PrintWriter(dump));
dump.append("\n").append(errorDump);
messageBody = dump.toString();
String messageBody = dump.toString();
Log.error("====== start unhandled exception dump");
Log.error(messageBody);
Log.error("====== end unhandled exception dump");
return this;
int result = show(messageBody, customMessage, cause, errorDump, flags);
return (flags & ALLOW_TERMINATE) == 0 || result == 1;
}
public static ErrorHandler error(String message, Throwable cause) {
return instance.init(message, cause);
}
public ErrorHandler preventReport() {
preventReport = true;
return this;
}
public ErrorHandler allowTerminate() {
allowTerminate = true;
return this;
}
public ErrorHandler preventContinue() {
preventContinue = true;
return this;
}
public ErrorHandler show() {
private static int show(final String messageBody, final String customMessage, final Throwable cause,
final String errorDump, final int flags) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
@@ -119,7 +89,7 @@ public class ErrorHandler {
String title = "opsu!dance error - " + customMessage;
String messageText = "opsu!dance has encountered an error.";
if (!preventReport) {
if ((flags & PREVENT_REPORT) == 0) {
messageText += " Please report this!";
}
JLabel message = new JLabel(messageText);
@@ -133,12 +103,27 @@ public class ErrorHandler {
textArea.setWrapStyleWord(true);
textArea.setText(messageBody);
Object[] messageComponents = new Object[] { message, new JScrollPane(textArea), createViewLogButton(), createReportButton() };
ActionListener reportAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
try {
URI url = createGithubIssueUrl(customMessage, cause, errorDump);
Desktop.getDesktop().browse(url);
} catch (IOException e) {
Log.warn("Could not open browser to report issue", e);
JOptionPane.showMessageDialog(null, "whoops could not launch a browser",
"errorception", JOptionPane.ERROR_MESSAGE);
}
}
};
Object[] messageComponents = new Object[] { message, new JScrollPane(textArea), createViewLogButton(),
createReportButton(flags, reportAction) };
String[] buttons;
if (!allowTerminate && !preventContinue) {
if ((flags & (ALLOW_TERMINATE | PREVENT_CONTINUE)) == 0) {
buttons = new String[] { "Ignore & continue" };
} else if (preventContinue) {
} else if ((flags & PREVENT_CONTINUE) == 0) {
buttons = new String[] { "Terminate" };
} else {
buttons = new String[] { "Terminate", "Ignore & continue" };
@@ -148,52 +133,46 @@ public class ErrorHandler {
frame.setUndecorated(true);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
int result = JOptionPane.showOptionDialog(frame,
messageComponents,
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
buttons,
buttons[buttons.length - 1]);
ignoreAndContinue = !allowTerminate || result == 1;
int result = JOptionPane.showOptionDialog(frame, messageComponents, title, JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE, null, buttons, buttons[buttons.length - 1]);
frame.dispose();
return this;
return result;
}
private JComponent createViewLogButton() {
private static JComponent createViewLogButton() {
return createButton("View log", Desktop.Action.OPEN, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
try {
Desktop.getDesktop().open(config.LOG_FILE);
} catch (IOException e) {
Log.warn("Could not open log file", e);
JOptionPane.showMessageDialog(null, "whoops could not open log file", "errorception", JOptionPane.ERROR_MESSAGE);
}
openLogfile();
}
});
}
private JComponent createReportButton() {
if (preventReport) {
private static void openLogfile() {
if (config == null) {
JOptionPane.showMessageDialog(null,
"Cannot open logfile, check your opsu! installation folder for .opsu.cfg",
"errorception", JOptionPane.ERROR_MESSAGE);
return;
}
try {
Desktop.getDesktop().open(config.LOG_FILE);
} catch (IOException e) {
Log.warn("Could not open log file", e);
JOptionPane.showMessageDialog(null, "whoops could not open log file",
"errorception", JOptionPane.ERROR_MESSAGE);
}
}
private static JComponent createReportButton(int flags, ActionListener reportAction) {
if ((flags & PREVENT_REPORT) > 0) {
return new JLabel();
}
return createButton("Report error", Desktop.Action.BROWSE, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
try {
Desktop.getDesktop().browse(createGithubIssueUrl());
} catch (IOException e) {
Log.warn("Could not open browser to report issue", e);
JOptionPane.showMessageDialog(null, "whoops could not launch a browser", "errorception", JOptionPane.ERROR_MESSAGE);
}
}
});
return createButton("Report error", Desktop.Action.BROWSE, reportAction);
}
private JButton createButton(String buttonText, Desktop.Action action, ActionListener listener) {
private static JButton createButton(String buttonText, Desktop.Action action, ActionListener listener) {
JButton button = new JButton(buttonText);
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action)) {
button.addActionListener(listener);
@@ -203,7 +182,7 @@ public class ErrorHandler {
return button;
}
private URI createGithubIssueUrl() {
private static URI createGithubIssueUrl(String customMessage, Throwable cause, String errorDump) {
StringWriter dump = new StringWriter();
dump.append(customMessage).append("\n");
@@ -228,7 +207,8 @@ public class ErrorHandler {
String issueTitle = "";
String issueBody = "";
try {
issueTitle = URLEncoder.encode("*** Unhandled " + cause.getClass().getSimpleName() + " " + customMessage, "UTF-8");
issueTitle = URLEncoder.encode("*** Unhandled " + cause.getClass().getSimpleName() + " " +
customMessage, "UTF-8");
issueBody = URLEncoder.encode(truncateGithubIssueBody(dump.toString()), "UTF-8");
} catch (UnsupportedEncodingException e) {
Log.warn("URLEncoder failed to encode the auto-filled issue report URL.", e);
@@ -236,7 +216,7 @@ public class ErrorHandler {
return URI.create(String.format(Constants.ISSUES_URL, issueTitle, issueBody));
}
private String truncateGithubIssueBody(String body) {
private static String truncateGithubIssueBody(String body) {
if (body.replaceAll("[^a-zA-Z+-]", "").length() < 1750) {
return body;
}
@@ -244,8 +224,4 @@ public class ErrorHandler {
return body.substring(0, 1640) + "** TRUNCATED **\n```";
}
public boolean shouldIgnoreAndContinue() {
return ignoreAndContinue;
}
}

View File

@@ -28,7 +28,7 @@ import itdelatrisu.opsu.ui.Colors;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import yugecin.opsudance.core.errorhandling.ErrorHandler;
import org.newdawn.slick.util.Log;
import yugecin.opsudance.events.BubNotifListener;
import yugecin.opsudance.utils.ManifestWrapper;
@@ -42,6 +42,7 @@ import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static yugecin.opsudance.core.errorhandling.ErrorHandler.*;
import static yugecin.opsudance.options.Options.*;
import static yugecin.opsudance.core.InstanceContainer.*;
@@ -201,7 +202,8 @@ public class Configuration {
}
File dir = new File(rootPath, "opsu");
if (!dir.isDirectory() && !dir.mkdir()) {
ErrorHandler.error(String.format("Failed to create configuration folder at '%s/opsu'.", rootPath), new Exception("empty")).preventReport().show();
explode(String.format("Failed to create configuration folder at '%s/opsu'.", rootPath),
new Exception("empty"), PREVENT_REPORT);
}
return dir;
}
@@ -252,7 +254,10 @@ public class Configuration {
BubNotifListener.EVENT.make().onBubNotif("Created " + fileName,
Colors.BUB_PURPLE);
} catch (Exception e) {
ErrorHandler.error("Failed to take a screenshot.", e).show();
Log.error("Could not take screenshot", e);
BubNotifListener.EVENT.make().onBubNotif(
"Failed to take a screenshot. See log file for details",
Colors.BUB_PURPLE);
}
}
}.start();

View File

@@ -28,11 +28,12 @@ import org.newdawn.slick.opengl.LoadableImageData;
import org.newdawn.slick.opengl.TGAImageData;
import org.newdawn.slick.util.Log;
import org.newdawn.slick.util.ResourceLoader;
import yugecin.opsudance.core.errorhandling.ErrorHandler;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import static yugecin.opsudance.core.errorhandling.ErrorHandler.*;
public class GLHelper {
/**
@@ -96,7 +97,7 @@ public class GLHelper {
IntBuffer tmp = BufferUtils.createIntBuffer(min * min);
Mouse.setNativeCursor(new Cursor(min, min, min / 2, min / 2, 1, tmp, null));
} catch (LWJGLException e) {
ErrorHandler.error("Cannot hide native cursor", e).show();
explode("Cannot hide native cursor", e, DEFAULT_OPTIONS);
}
}
@@ -104,7 +105,7 @@ public class GLHelper {
try {
Mouse.setNativeCursor(null);
} catch (LWJGLException e) {
ErrorHandler.error("Cannot show native cursor", e).show();
explode("Cannot show native cursor", e, DEFAULT_OPTIONS);
}
}