diff --git a/src/itdelatrisu/opsu/GameImage.java b/src/itdelatrisu/opsu/GameImage.java index c54c9df0..e5126b3f 100644 --- a/src/itdelatrisu/opsu/GameImage.java +++ b/src/itdelatrisu/opsu/GameImage.java @@ -869,7 +869,8 @@ public enum GameImage { skinImages = null; } } catch (SlickException e) { - ErrorHandler.error(String.format("Failed to destroy beatmap skin images for '%s'.", this.name()), e).show(); + String msg = String.format("Failed to destroy beatmap skin images for '%s'.", this.name()); + ErrorHandler.explode(msg, e, ErrorHandler.DEFAULT_OPTIONS); } } diff --git a/src/itdelatrisu/opsu/Utils.java b/src/itdelatrisu/opsu/Utils.java index 14eb4640..9f757eb6 100644 --- a/src/itdelatrisu/opsu/Utils.java +++ b/src/itdelatrisu/opsu/Utils.java @@ -46,9 +46,8 @@ import org.newdawn.slick.util.Log; import com.sun.jna.platform.FileUtils; import yugecin.opsudance.core.NotNull; import yugecin.opsudance.core.Nullable; -import yugecin.opsudance.core.errorhandling.ErrorHandler; -import yugecin.opsudance.events.BubNotifListener; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; import static yugecin.opsudance.core.InstanceContainer.*; /** @@ -313,7 +312,7 @@ public class Utils { try { json = new JSONObject(s); } catch (JSONException e) { - ErrorHandler.error("Failed to create JSON object.", e).show(); + explode("Failed to create JSON object.", e, DEFAULT_OPTIONS); } } return json; @@ -332,7 +331,7 @@ public class Utils { try { json = new JSONArray(s); } catch (JSONException e) { - ErrorHandler.error("Failed to create JSON array.", e).show(); + explode("Failed to create JSON array.", e, DEFAULT_OPTIONS); } } return json; @@ -374,7 +373,7 @@ public class Utils { result.append(String.format("%02x", b)); return result.toString(); } catch (NoSuchAlgorithmException | IOException e) { - ErrorHandler.error("Failed to calculate MD5 hash.", e).show(); + explode("Failed to calculate MD5 hash.", e, DEFAULT_OPTIONS); } return null; } diff --git a/src/itdelatrisu/opsu/audio/MultiClip.java b/src/itdelatrisu/opsu/audio/MultiClip.java index d314815f..e22cd4cf 100644 --- a/src/itdelatrisu/opsu/audio/MultiClip.java +++ b/src/itdelatrisu/opsu/audio/MultiClip.java @@ -1,7 +1,5 @@ package itdelatrisu.opsu.audio; -import yugecin.opsudance.core.errorhandling.ErrorHandler; - import java.io.IOException; import java.util.Iterator; import java.util.LinkedList; @@ -14,6 +12,8 @@ import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineListener; import javax.sound.sampled.LineUnavailableException; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; + /** * Extension of Clip that allows playing multiple copies of a Clip simultaneously. * http://stackoverflow.com/questions/1854616/ @@ -194,7 +194,8 @@ public class MultiClip { try { audioIn.close(); } catch (IOException e) { - ErrorHandler.error(String.format("Could not close AudioInputStream for MultiClip %s.", name), e).show(); + explode(String.format("Could not close AudioInputStream for MultiClip %s.", name), e, + DEFAULT_OPTIONS); } } } diff --git a/src/itdelatrisu/opsu/audio/MusicController.java b/src/itdelatrisu/opsu/audio/MusicController.java index ce914633..eee4135a 100644 --- a/src/itdelatrisu/opsu/audio/MusicController.java +++ b/src/itdelatrisu/opsu/audio/MusicController.java @@ -45,10 +45,10 @@ import org.newdawn.slick.openal.SoundStore; import org.newdawn.slick.util.Log; import org.newdawn.slick.util.ResourceLoader; import org.tritonus.share.sampled.file.TAudioFileFormat; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import yugecin.opsudance.events.BarNotifListener; import yugecin.opsudance.events.BubNotifListener; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; import static yugecin.opsudance.options.Options.*; /** @@ -576,7 +576,7 @@ public class MusicController { player = null; } catch (Exception e) { - ErrorHandler.error("Failed to destroy OpenAL.", e).show(); + explode("Failed to destroy OpenAL.", e, DEFAULT_OPTIONS); } } diff --git a/src/itdelatrisu/opsu/audio/SoundController.java b/src/itdelatrisu/opsu/audio/SoundController.java index 1d53db36..659b9fbb 100644 --- a/src/itdelatrisu/opsu/audio/SoundController.java +++ b/src/itdelatrisu/opsu/audio/SoundController.java @@ -39,12 +39,12 @@ import javax.sound.sampled.LineUnavailableException; import itdelatrisu.opsu.ui.Colors; import org.newdawn.slick.SlickException; import org.newdawn.slick.util.ResourceLoader; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import yugecin.opsudance.events.BarNotifListener; import yugecin.opsudance.events.BubNotifListener; import yugecin.opsudance.options.Configuration; import yugecin.opsudance.skinning.SkinService; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; import static yugecin.opsudance.options.Options.*; /** @@ -104,7 +104,7 @@ public class SoundController { AudioInputStream audioIn = AudioSystem.getAudioInputStream(url); return loadClip(ref, audioIn, isMP3); } catch (Exception e) { - ErrorHandler.error(String.format("Failed to load file '%s'.", ref), e).show(); + explode(String.format("Failed to load file '%s'.", ref), e, DEFAULT_OPTIONS); return null; } } @@ -285,7 +285,7 @@ public class SoundController { try { clip.start(volume, listener); } catch (LineUnavailableException e) { - ErrorHandler.error(String.format("Could not start a clip '%s'.", clip.getName()), e).show(); + explode(String.format("Could not start a clip '%s'.", clip.getName()), e, DEFAULT_OPTIONS); } } } diff --git a/src/itdelatrisu/opsu/beatmap/BeatmapParser.java b/src/itdelatrisu/opsu/beatmap/BeatmapParser.java index 8fbf16fc..7550d0af 100644 --- a/src/itdelatrisu/opsu/beatmap/BeatmapParser.java +++ b/src/itdelatrisu/opsu/beatmap/BeatmapParser.java @@ -35,10 +35,10 @@ import itdelatrisu.opsu.ui.Colors; import org.newdawn.slick.Color; import org.newdawn.slick.util.Log; import yugecin.opsudance.core.Nullable; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import yugecin.opsudance.events.BubNotifListener; import yugecin.opsudance.skinning.SkinService; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; import static yugecin.opsudance.core.InstanceContainer.*; import static yugecin.opsudance.options.Options.*; @@ -250,7 +250,7 @@ public class BeatmapParser { } catch (IOException e) { logAndShowErrorNotification(e, "Failed to read file '%s'.", map.getFile().getAbsolutePath()); } catch (NoSuchAlgorithmException e) { - ErrorHandler.error("Failed to get MD5 hash stream.", e).show(); + explode("Failed to get MD5 hash stream.", e, DEFAULT_OPTIONS); // retry without MD5 hasNoMD5Algorithm = true; @@ -653,7 +653,7 @@ public class BeatmapParser { } catch (IOException e) { logAndShowErrorNotification(e, "Failed to read file '%s'.", file.getAbsolutePath()); } catch (NoSuchAlgorithmException e) { - ErrorHandler.error("Failed to get MD5 hash stream.", e).show(); + explode("Failed to get MD5 hash stream.", e, DEFAULT_OPTIONS); // retry without MD5 hasNoMD5Algorithm = true; @@ -811,8 +811,9 @@ public class BeatmapParser { // check that all objects were parsed if (objectIndex != beatmap.objects.length) - ErrorHandler.error(String.format("Parsed %d objects for beatmap '%s', %d objects expected.", - objectIndex, beatmap.toString(), beatmap.objects.length), new Exception("no")).show(); + explode(String.format("Parsed %d objects for beatmap '%s', %d objects expected.", + objectIndex, beatmap.toString(), beatmap.objects.length), new Exception("no"), + DEFAULT_OPTIONS); } catch (IOException e) { logAndShowErrorNotification(e, "Failed to read file '%s'.", beatmap.getFile().getAbsolutePath()); diff --git a/src/itdelatrisu/opsu/db/BeatmapDB.java b/src/itdelatrisu/opsu/db/BeatmapDB.java index 20f7037f..745271db 100644 --- a/src/itdelatrisu/opsu/db/BeatmapDB.java +++ b/src/itdelatrisu/opsu/db/BeatmapDB.java @@ -33,8 +33,9 @@ import java.util.List; import java.util.Map; import org.newdawn.slick.util.Log; -import yugecin.opsudance.core.errorhandling.ErrorHandler; -import yugecin.opsudance.options.Configuration; + +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; +import static yugecin.opsudance.core.InstanceContainer.*; /** * Handles connections and queries with the cached beatmap database. @@ -89,17 +90,10 @@ public class BeatmapDB { /** Current size of beatmap cache table. */ private static int cacheSize = -1; - // This class should not be instantiated. - private BeatmapDB() {} - - private static Configuration config; // TODO - /** * Initializes the database connection. */ - public static void init(Configuration config) { - BeatmapDB.config = config; - + public static void init() { // create a database connection connection = DBController.createConnection(config.BEATMAP_DB.getPath()); if (connection == null) @@ -115,7 +109,7 @@ public class BeatmapDB { try { updateSizeStmt = connection.prepareStatement("REPLACE INTO info (key, value) VALUES ('size', ?)"); } catch (SQLException e) { - ErrorHandler.error("Failed to prepare beatmap statements.", e).show(); + explode("Failed to prepare beatmap statements.", e, DEFAULT_OPTIONS); } // retrieve the cache size @@ -137,7 +131,7 @@ public class BeatmapDB { updatePlayStatsStmt = connection.prepareStatement("UPDATE beatmaps SET playCount = ?, lastPlayed = ? WHERE dir = ? AND file = ?"); setFavoriteStmt = connection.prepareStatement("UPDATE beatmaps SET favorite = ? WHERE dir = ? AND file = ?"); } catch (SQLException e) { - ErrorHandler.error("Failed to prepare beatmap statements.", e).show(); + explode("Failed to prepare beatmap statements.", e, DEFAULT_OPTIONS); } } @@ -175,7 +169,7 @@ public class BeatmapDB { sql = String.format("INSERT OR IGNORE INTO info(key, value) VALUES('version', '%s')", DATABASE_VERSION); stmt.executeUpdate(sql); } catch (SQLException e) { - ErrorHandler.error("Coudl not create beatmap database.", e).show(); + explode("Could not create beatmap database.", e, DEFAULT_OPTIONS); } } @@ -227,7 +221,7 @@ public class BeatmapDB { ps.close(); } } catch (SQLException e) { - ErrorHandler.error("Failed to update beatmap database.", e).show(); + explode("Failed to update beatmap database.", e, DEFAULT_OPTIONS); } } @@ -245,7 +239,7 @@ public class BeatmapDB { } rs.close(); } catch (SQLException e) { - ErrorHandler.error("Could not get beatmap cache size.", e).show(); + explode("Could not get beatmap cache size.", e, DEFAULT_OPTIONS); } } @@ -260,7 +254,7 @@ public class BeatmapDB { updateSizeStmt.setString(1, Integer.toString(Math.max(cacheSize, 0))); updateSizeStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error("Could not update beatmap cache size.", e).show(); + explode("Could not update beatmap cache size.", e, DEFAULT_OPTIONS); } } @@ -278,7 +272,7 @@ public class BeatmapDB { cacheSize = 0; updateCacheSize(); } catch (SQLException e) { - ErrorHandler.error("Could not drop beatmap database.", e).show(); + explode("Could not drop beatmap database.", e, DEFAULT_OPTIONS); } createDatabase(); } @@ -296,7 +290,7 @@ public class BeatmapDB { cacheSize += insertStmt.executeUpdate(); updateCacheSize(); } catch (SQLException e) { - ErrorHandler.error("Failed to add beatmap to database.", e).show(); + explode("Failed to add beatmap to database.", e, DEFAULT_OPTIONS); } } @@ -349,7 +343,7 @@ public class BeatmapDB { // update cache size updateCacheSize(); } catch (SQLException e) { - ErrorHandler.error("Failed to add beatmaps to database.", e).show(); + explode("Failed to add beatmaps to database.", e, DEFAULT_OPTIONS); } } @@ -437,7 +431,7 @@ public class BeatmapDB { } rs.close(); } catch (SQLException e) { - ErrorHandler.error("Failed to load Beatmap from database.", e).show(); + explode("Failed to load Beatmap from database.", e, DEFAULT_OPTIONS); } } @@ -500,7 +494,7 @@ public class BeatmapDB { } rs.close(); } catch (SQLException e) { - ErrorHandler.error("Failed to load beatmaps from database.", e).show(); + explode("Failed to load beatmaps from database.", e, DEFAULT_OPTIONS); } } @@ -601,7 +595,7 @@ public class BeatmapDB { rs.close(); return map; } catch (SQLException e) { - ErrorHandler.error("Failed to get last modified map from database.", e).show(); + explode("Failed to get last modified map from database.", e, DEFAULT_OPTIONS); return null; } } @@ -621,7 +615,7 @@ public class BeatmapDB { cacheSize -= deleteMapStmt.executeUpdate(); updateCacheSize(); } catch (SQLException e) { - ErrorHandler.error("Failed to delete beatmap entry from database.", e).show(); + explode("Failed to delete beatmap entry from database.", e, DEFAULT_OPTIONS); } } @@ -638,7 +632,7 @@ public class BeatmapDB { cacheSize -= deleteGroupStmt.executeUpdate(); updateCacheSize(); } catch (SQLException e) { - ErrorHandler.error("Failed to delete beatmap group entry from database.", e).show(); + explode("Failed to delete beatmap group entry from database.", e, DEFAULT_OPTIONS); } } @@ -656,8 +650,8 @@ public class BeatmapDB { setStarsStmt.setString(3, beatmap.getFile().getName()); setStarsStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error(String.format("Failed to save star rating '%.4f' for beatmap '%s' in database.", - beatmap.starRating, beatmap.toString()), e).show(); + explode(String.format("Failed to save star rating '%.4f' for beatmap '%s' in database.", + beatmap.starRating, beatmap.toString()), e, DEFAULT_OPTIONS); } } @@ -676,8 +670,8 @@ public class BeatmapDB { updatePlayStatsStmt.setString(4, beatmap.getFile().getName()); updatePlayStatsStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error(String.format("Failed to update play statistics for beatmap '%s' in database.", - beatmap.toString()), e).show(); + explode(String.format("Failed to update play statistics for beatmap '%s' in database.", + beatmap.toString()), e, DEFAULT_OPTIONS); } } @@ -695,8 +689,8 @@ public class BeatmapDB { setFavoriteStmt.setString(3, beatmap.getFile().getName()); setFavoriteStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error(String.format("Failed to update favorite status for beatmap '%s' in database.", - beatmap.toString()), e).show(); + explode(String.format("Failed to update favorite status for beatmap '%s' in database.", + beatmap.toString()), e, DEFAULT_OPTIONS); } } @@ -716,7 +710,7 @@ public class BeatmapDB { connection.close(); connection = null; } catch (SQLException e) { - ErrorHandler.error("Failed to close beatmap database.", e).show(); + explode("Failed to close beatmap database.", e, DEFAULT_OPTIONS); } } } diff --git a/src/itdelatrisu/opsu/db/DBController.java b/src/itdelatrisu/opsu/db/DBController.java index d6223a9e..87ecfbec 100644 --- a/src/itdelatrisu/opsu/db/DBController.java +++ b/src/itdelatrisu/opsu/db/DBController.java @@ -18,13 +18,12 @@ package itdelatrisu.opsu.db; -import yugecin.opsudance.core.errorhandling.ErrorHandler; -import yugecin.opsudance.options.Configuration; - import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; + /** * Database controller. */ @@ -35,17 +34,17 @@ public class DBController { /** * Initializes all databases. */ - public static void init(Configuration config) { + public static void init() { // load the sqlite-JDBC driver using the current class loader try { Class.forName("org.sqlite.JDBC"); } catch (ClassNotFoundException e) { - ErrorHandler.error("Could not load sqlite-JDBC driver.", e).show(); + explode("Could not load sqlite-JDBC driver.", e, DEFAULT_OPTIONS); } // initialize the databases - BeatmapDB.init(config); - ScoreDB.init(config); + BeatmapDB.init(); + ScoreDB.init(); } /** @@ -66,7 +65,7 @@ public class DBController { return DriverManager.getConnection(String.format("jdbc:sqlite:%s", path)); } catch (SQLException e) { // if the error message is "out of memory", it probably means no database file is found - ErrorHandler.error(String.format("Could not connect to database: '%s'.", path), e).show(); + explode(String.format("Could not connect to database: '%s'.", path), e, DEFAULT_OPTIONS); return null; } } diff --git a/src/itdelatrisu/opsu/db/ScoreDB.java b/src/itdelatrisu/opsu/db/ScoreDB.java index a195a87d..1736e9ef 100644 --- a/src/itdelatrisu/opsu/db/ScoreDB.java +++ b/src/itdelatrisu/opsu/db/ScoreDB.java @@ -20,8 +20,6 @@ package itdelatrisu.opsu.db; import itdelatrisu.opsu.ScoreData; import itdelatrisu.opsu.beatmap.Beatmap; -import yugecin.opsudance.core.errorhandling.ErrorHandler; -import yugecin.opsudance.options.Configuration; import java.sql.Connection; import java.sql.PreparedStatement; @@ -36,6 +34,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; +import static yugecin.opsudance.core.InstanceContainer.*; + /** * Handles connections and queries with the scores database. */ @@ -77,13 +78,10 @@ public class ScoreDB { /** Score deletion statement. */ private static PreparedStatement deleteSongStmt, deleteScoreStmt; - // This class should not be instantiated. - private ScoreDB() {} - /** * Initializes the database connection. */ - public static void init(Configuration config) { + public static void init() { // create a database connection connection = DBController.createConnection(config.SCORE_DB.getPath()); if (connection == null) @@ -124,7 +122,7 @@ public class ScoreDB { // TODO: extra playerName checks not needed if name is guaranteed not null ); } catch (SQLException e) { - ErrorHandler.error("Failed to prepare score statements.", e).show(); + explode("Failed to prepare score statements.", e, DEFAULT_OPTIONS); } } @@ -157,7 +155,7 @@ public class ScoreDB { sql = String.format("INSERT OR IGNORE INTO info(key, value) VALUES('version', %d)", DATABASE_VERSION); stmt.executeUpdate(sql); } catch (SQLException e) { - ErrorHandler.error("Could not create score database.", e).show(); + explode("Could not create score database.", e, DEFAULT_OPTIONS); } } @@ -209,7 +207,7 @@ public class ScoreDB { ps.close(); } } catch (SQLException e) { - ErrorHandler.error("Failed to update score database.", e).show(); + explode("Failed to update score database.", e, DEFAULT_OPTIONS); } } @@ -227,7 +225,7 @@ public class ScoreDB { insertStmt.setString(19, data.playerName); insertStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error("Failed to save score to database.", e).show(); + explode("Failed to save score to database.", e, DEFAULT_OPTIONS); } } @@ -247,7 +245,7 @@ public class ScoreDB { deleteScoreStmt.setString(21, data.playerName); deleteScoreStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error("Failed to delete score from database.", e).show(); + explode("Failed to delete score from database.", e, DEFAULT_OPTIONS); } } @@ -267,7 +265,7 @@ public class ScoreDB { deleteSongStmt.setString(5, beatmap.version); deleteSongStmt.executeUpdate(); } catch (SQLException e) { - ErrorHandler.error("Failed to delete scores from database.", e).show(); + explode("Failed to delete scores from database.", e, DEFAULT_OPTIONS); } } @@ -335,7 +333,7 @@ public class ScoreDB { } rs.close(); } catch (SQLException e) { - ErrorHandler.error("Failed to read scores from database.", e).show(); + explode("Failed to read scores from database.", e, DEFAULT_OPTIONS); return null; } return getSortedArray(list); @@ -377,7 +375,7 @@ public class ScoreDB { map.put(version, getSortedArray(list)); rs.close(); } catch (SQLException e) { - ErrorHandler.error("Failed to read scores from database.", e).show(); + explode("Failed to read scores from database.", e, DEFAULT_OPTIONS); return null; } return map; @@ -406,7 +404,7 @@ public class ScoreDB { connection.close(); connection = null; } catch (SQLException e) { - ErrorHandler.error("Failed to close score database.", e).show(); + explode("Failed to close score database.", e, DEFAULT_OPTIONS); } } } diff --git a/src/itdelatrisu/opsu/downloads/Download.java b/src/itdelatrisu/opsu/downloads/Download.java index a6a7b585..1b65d5d3 100644 --- a/src/itdelatrisu/opsu/downloads/Download.java +++ b/src/itdelatrisu/opsu/downloads/Download.java @@ -35,9 +35,10 @@ import java.nio.file.StandardCopyOption; import itdelatrisu.opsu.ui.Colors; import org.newdawn.slick.util.Log; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import yugecin.opsudance.events.BubNotifListener; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; + /** * File download. */ @@ -144,7 +145,7 @@ public class Download { this.url = new URL(remoteURL); } catch (MalformedURLException e) { this.status = Status.ERROR; - ErrorHandler.error(String.format("Bad download URL: '%s'", remoteURL), e).show(); + explode(String.format("Bad download URL: '%s'", remoteURL), e, DEFAULT_OPTIONS); return; } this.localPath = localPath; @@ -421,7 +422,7 @@ public class Download { } } catch (IOException e) { this.status = Status.ERROR; - ErrorHandler.error("Failed to cancel download.", e).show(); + explode("Failed to cancel download.", e, DEFAULT_OPTIONS); } } } diff --git a/src/itdelatrisu/opsu/downloads/Updater.java b/src/itdelatrisu/opsu/downloads/Updater.java index 29772e37..f0d95efd 100644 --- a/src/itdelatrisu/opsu/downloads/Updater.java +++ b/src/itdelatrisu/opsu/downloads/Updater.java @@ -36,9 +36,9 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.newdawn.slick.util.Log; import org.newdawn.slick.util.ResourceLoader; import yugecin.opsudance.core.Constants; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import yugecin.opsudance.events.BarNotifListener; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; import static yugecin.opsudance.core.InstanceContainer.*; /** @@ -291,7 +291,7 @@ public class Updater { pb.start(); } catch (IOException e) { status = Status.INTERNAL_ERROR; - ErrorHandler.error("Failed to start new process.", e).show(); + explode("Failed to start new process.", e, DEFAULT_OPTIONS); } } } diff --git a/src/itdelatrisu/opsu/downloads/servers/BloodcatServer.java b/src/itdelatrisu/opsu/downloads/servers/BloodcatServer.java index 29213e2e..628cd417 100644 --- a/src/itdelatrisu/opsu/downloads/servers/BloodcatServer.java +++ b/src/itdelatrisu/opsu/downloads/servers/BloodcatServer.java @@ -33,7 +33,8 @@ import java.util.Date; import org.json.JSONArray; import org.json.JSONObject; -import yugecin.opsudance.core.errorhandling.ErrorHandler; + +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; /** * Download server: http://bloodcat.com/osu/ @@ -95,7 +96,7 @@ public class BloodcatServer extends DownloadServer { resultCount++; this.totalResults = resultCount; } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem loading result list for query '%s'.", query), e).show(); + explode(String.format("Problem loading result list for query '%s'.", query), e, DEFAULT_OPTIONS); } return nodes; } diff --git a/src/itdelatrisu/opsu/downloads/servers/HexideServer.java b/src/itdelatrisu/opsu/downloads/servers/HexideServer.java index 0f5ca4f5..9b504f04 100644 --- a/src/itdelatrisu/opsu/downloads/servers/HexideServer.java +++ b/src/itdelatrisu/opsu/downloads/servers/HexideServer.java @@ -29,7 +29,8 @@ import java.net.URLEncoder; import org.json.JSONArray; import org.json.JSONObject; -import yugecin.opsudance.core.errorhandling.ErrorHandler; + +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; /** * Download server: https://osu.hexide.com/ @@ -126,7 +127,7 @@ public class HexideServer extends DownloadServer { // all results at once; this approach just gets pagination correct. this.totalResults = arr.length() + resultIndex; } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem loading result list for query '%s'.", query), e).show(); + explode(String.format("Problem loading result list for query '%s'.", query), e, DEFAULT_OPTIONS); } return nodes; } diff --git a/src/itdelatrisu/opsu/downloads/servers/MengSkyServer.java b/src/itdelatrisu/opsu/downloads/servers/MengSkyServer.java index 56525536..ff615f6c 100644 --- a/src/itdelatrisu/opsu/downloads/servers/MengSkyServer.java +++ b/src/itdelatrisu/opsu/downloads/servers/MengSkyServer.java @@ -29,7 +29,8 @@ import java.net.URLEncoder; import org.json.JSONArray; import org.json.JSONObject; -import yugecin.opsudance.core.errorhandling.ErrorHandler; + +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; /** * Download server: http://osu.mengsky.net/ @@ -98,7 +99,7 @@ public class MengSkyServer extends DownloadServer { } this.totalResults = resultCount; } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem loading result list for query '%s'.", query), e).show(); + explode(String.format("Problem loading result list for query '%s'.", query), e, DEFAULT_OPTIONS); } return nodes; } diff --git a/src/itdelatrisu/opsu/downloads/servers/MnetworkServer.java b/src/itdelatrisu/opsu/downloads/servers/MnetworkServer.java index 7fd33738..75e497c6 100644 --- a/src/itdelatrisu/opsu/downloads/servers/MnetworkServer.java +++ b/src/itdelatrisu/opsu/downloads/servers/MnetworkServer.java @@ -20,7 +20,6 @@ package itdelatrisu.opsu.downloads.servers; import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.downloads.DownloadNode; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -32,6 +31,8 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; + /** * Download server: http://osu.uu.gl/ */ @@ -118,7 +119,7 @@ public class MnetworkServer extends DownloadServer { // store total result count this.totalResults = nodes.length; } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem loading result list for query '%s'.", query), e).show(); + explode(String.format("Problem loading result list for query '%s'.", query), e, DEFAULT_OPTIONS); } return nodes; } diff --git a/src/itdelatrisu/opsu/downloads/servers/OsuMirrorServer.java b/src/itdelatrisu/opsu/downloads/servers/OsuMirrorServer.java index c7073c99..7ba31aec 100644 --- a/src/itdelatrisu/opsu/downloads/servers/OsuMirrorServer.java +++ b/src/itdelatrisu/opsu/downloads/servers/OsuMirrorServer.java @@ -35,7 +35,8 @@ import java.util.TimeZone; import org.json.JSONArray; import org.json.JSONObject; -import yugecin.opsudance.core.errorhandling.ErrorHandler; + +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; /** * Download server: http://loli.al/ @@ -121,7 +122,7 @@ public class OsuMirrorServer extends DownloadServer { else this.totalResults = maxServerID; } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem loading result list for query '%s'.", query), e).show(); + explode(String.format("Problem loading result list for query '%s'.", query), e, DEFAULT_OPTIONS); } return nodes; } diff --git a/src/itdelatrisu/opsu/downloads/servers/YaSOnlineServer.java b/src/itdelatrisu/opsu/downloads/servers/YaSOnlineServer.java index 605e3f05..d732ed87 100644 --- a/src/itdelatrisu/opsu/downloads/servers/YaSOnlineServer.java +++ b/src/itdelatrisu/opsu/downloads/servers/YaSOnlineServer.java @@ -33,7 +33,8 @@ import java.util.Iterator; import java.util.List; import org.json.JSONObject; -import yugecin.opsudance.core.errorhandling.ErrorHandler; + +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; /** * Download server: http://osu.yas-online.net/ @@ -112,7 +113,8 @@ public class YaSOnlineServer extends DownloadServer { String downloadLink = item.getString("downloadLink"); return String.format(DOWNLOAD_FETCH_URL, downloadLink); } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem retrieving download URL for beatmap '%d'.", beatmapSetID), e).show(); + explode(String.format("Problem retrieving download URL for beatmap '%d'.", beatmapSetID), e, + DEFAULT_OPTIONS); return null; } finally { Utils.setSSLCertValidation(true); @@ -184,7 +186,7 @@ public class YaSOnlineServer extends DownloadServer { else this.totalResults = maxServerID; } catch (MalformedURLException | UnsupportedEncodingException e) { - ErrorHandler.error(String.format("Problem loading result list for query '%s'.", query), e).show(); + explode(String.format("Problem loading result list for query '%s'.", query), e, DEFAULT_OPTIONS); } finally { Utils.setSSLCertValidation(true); } diff --git a/src/itdelatrisu/opsu/replay/Replay.java b/src/itdelatrisu/opsu/replay/Replay.java index 23a1c8eb..9296f55e 100644 --- a/src/itdelatrisu/opsu/replay/Replay.java +++ b/src/itdelatrisu/opsu/replay/Replay.java @@ -44,9 +44,9 @@ import org.apache.commons.compress.compressors.lzma.LZMACompressorInputStream; import org.newdawn.slick.util.Log; import lzma.streams.LzmaOutputStream; -import yugecin.opsudance.core.errorhandling.ErrorHandler; import yugecin.opsudance.events.BubNotifListener; +import static yugecin.opsudance.core.errorhandling.ErrorHandler.*; import static yugecin.opsudance.core.InstanceContainer.*; /** @@ -344,7 +344,7 @@ public class Replay { compressedOut.write(bytes); } catch (IOException e) { // possible OOM: https://github.com/jponge/lzma-java/issues/9 - ErrorHandler.error("LZMA compression failed (possible out-of-memory error).", e).show(); + explode("LZMA compression failed (possible out-of-memory error).", e, DEFAULT_OPTIONS); } compressedOut.close(); bout.close(); @@ -358,7 +358,7 @@ public class Replay { writer.close(); } catch (IOException e) { - ErrorHandler.error("Could not save replay data.", e).show(); + explode("Could not save replay data.", e, DEFAULT_OPTIONS); } } }.start(); diff --git a/src/yugecin/opsudance/OpsuDance.java b/src/yugecin/opsudance/OpsuDance.java index 0f77d0ad..9bcc9895 100644 --- a/src/yugecin/opsudance/OpsuDance.java +++ b/src/yugecin/opsudance/OpsuDance.java @@ -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); } diff --git a/src/yugecin/opsudance/core/DisplayContainer.java b/src/yugecin/opsudance/core/DisplayContainer.java index 6722f49b..3d6d5315 100644 --- a/src/yugecin/opsudance/core/DisplayContainer.java +++ b/src/yugecin/opsudance/core/DisplayContainer.java @@ -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); } diff --git a/src/yugecin/opsudance/core/errorhandling/ErrorHandler.java b/src/yugecin/opsudance/core/errorhandling/ErrorHandler.java index 2832c26f..2a3ef34f 100644 --- a/src/yugecin/opsudance/core/errorhandling/ErrorHandler.java +++ b/src/yugecin/opsudance/core/errorhandling/ErrorHandler.java @@ -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; - } - } diff --git a/src/yugecin/opsudance/options/Configuration.java b/src/yugecin/opsudance/options/Configuration.java index 78c29dbe..d61fdebc 100644 --- a/src/yugecin/opsudance/options/Configuration.java +++ b/src/yugecin/opsudance/options/Configuration.java @@ -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(); diff --git a/src/yugecin/opsudance/utils/GLHelper.java b/src/yugecin/opsudance/utils/GLHelper.java index 66db778b..c43de64b 100644 --- a/src/yugecin/opsudance/utils/GLHelper.java +++ b/src/yugecin/opsudance/utils/GLHelper.java @@ -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); } }