From a7654e49cab8f354d0ee0966896f8cb6f0843e35 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Wed, 3 Jan 2024 15:20:34 -0500 Subject: [PATCH] Cleaned up profile loading exceptions. --- .../com/andrewlalis/perfin/PerfinApp.java | 7 +++--- .../control/ProfilesViewController.java | 10 +++------ .../DataSourceInitializationException.java | 11 ---------- .../perfin/data/ProfileLoadException.java | 11 ++++++++++ .../data/impl/JdbcDataSourceFactory.java | 22 +++++++++++-------- .../perfin/data/util/FileUtil.java | 8 +++++-- .../com/andrewlalis/perfin/model/Profile.java | 16 ++++++++++---- .../perfin/view/StartupSplashScreen.java | 5 +++++ 8 files changed, 53 insertions(+), 37 deletions(-) delete mode 100644 src/main/java/com/andrewlalis/perfin/data/DataSourceInitializationException.java create mode 100644 src/main/java/com/andrewlalis/perfin/data/ProfileLoadException.java diff --git a/src/main/java/com/andrewlalis/perfin/PerfinApp.java b/src/main/java/com/andrewlalis/perfin/PerfinApp.java index e10b067..aba5e31 100644 --- a/src/main/java/com/andrewlalis/perfin/PerfinApp.java +++ b/src/main/java/com/andrewlalis/perfin/PerfinApp.java @@ -2,8 +2,7 @@ package com.andrewlalis.perfin; import com.andrewlalis.javafx_scene_router.AnchorPaneRouterView; import com.andrewlalis.javafx_scene_router.SceneRouter; -import com.andrewlalis.perfin.control.Popups; -import com.andrewlalis.perfin.data.DataSourceInitializationException; +import com.andrewlalis.perfin.data.ProfileLoadException; import com.andrewlalis.perfin.model.Profile; import com.andrewlalis.perfin.view.ImageCache; import com.andrewlalis.perfin.view.SceneUtil; @@ -93,8 +92,8 @@ public class PerfinApp extends Application { msgConsumer.accept("Loading the most recent profile."); try { Profile.loadLast(); - } catch (DataSourceInitializationException e) { - Popups.error(e.getMessage()); + } catch (ProfileLoadException e) { + msgConsumer.accept("Failed to load the profile: " + e.getMessage()); throw e; } } diff --git a/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java b/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java index 1027a26..ef0f723 100644 --- a/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java +++ b/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java @@ -1,7 +1,7 @@ package com.andrewlalis.perfin.control; import com.andrewlalis.perfin.PerfinApp; -import com.andrewlalis.perfin.data.DataSourceInitializationException; +import com.andrewlalis.perfin.data.ProfileLoadException; import com.andrewlalis.perfin.data.util.FileUtil; import com.andrewlalis.perfin.model.Profile; import com.andrewlalis.perfin.view.ProfilesStage; @@ -121,12 +121,8 @@ public class ProfilesViewController { router.navigate("accounts"); if (showPopup) Popups.message("The profile \"" + name + "\" has been loaded."); return true; - } catch (IOException e) { - e.printStackTrace(System.err); - Popups.error("Failed to load profile: " + e.getMessage()); - return false; - } catch (DataSourceInitializationException e) { - Popups.error("Failed to initialize the profile's data: " + e.getMessage()); + } catch (ProfileLoadException e) { + Popups.error("Failed to load the profile: " + e.getMessage()); return false; } } diff --git a/src/main/java/com/andrewlalis/perfin/data/DataSourceInitializationException.java b/src/main/java/com/andrewlalis/perfin/data/DataSourceInitializationException.java deleted file mode 100644 index 3c8305a..0000000 --- a/src/main/java/com/andrewlalis/perfin/data/DataSourceInitializationException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.andrewlalis.perfin.data; - -public class DataSourceInitializationException extends Exception { - public DataSourceInitializationException(String message) { - super(message); - } - - public DataSourceInitializationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/com/andrewlalis/perfin/data/ProfileLoadException.java b/src/main/java/com/andrewlalis/perfin/data/ProfileLoadException.java new file mode 100644 index 0000000..2359c24 --- /dev/null +++ b/src/main/java/com/andrewlalis/perfin/data/ProfileLoadException.java @@ -0,0 +1,11 @@ +package com.andrewlalis.perfin.data; + +public class ProfileLoadException extends Exception { + public ProfileLoadException(String message) { + super(message); + } + + public ProfileLoadException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/andrewlalis/perfin/data/impl/JdbcDataSourceFactory.java b/src/main/java/com/andrewlalis/perfin/data/impl/JdbcDataSourceFactory.java index f1a7201..e5a8d9b 100644 --- a/src/main/java/com/andrewlalis/perfin/data/impl/JdbcDataSourceFactory.java +++ b/src/main/java/com/andrewlalis/perfin/data/impl/JdbcDataSourceFactory.java @@ -1,7 +1,7 @@ package com.andrewlalis.perfin.data.impl; import com.andrewlalis.perfin.data.DataSource; -import com.andrewlalis.perfin.data.DataSourceInitializationException; +import com.andrewlalis.perfin.data.ProfileLoadException; import com.andrewlalis.perfin.data.util.FileUtil; import com.andrewlalis.perfin.model.Profile; import org.slf4j.Logger; @@ -32,7 +32,7 @@ public class JdbcDataSourceFactory { */ public static final int SCHEMA_VERSION = 1; - public DataSource getDataSource(String profileName) throws DataSourceInitializationException { + public DataSource getDataSource(String profileName) throws ProfileLoadException { final boolean dbExists = Files.exists(getDatabaseFile(profileName)); if (!dbExists) { log.info("Creating new database for profile {}.", profileName); @@ -43,7 +43,7 @@ public class JdbcDataSourceFactory { loadedSchemaVersion = getSchemaVersion(profileName); } catch (IOException e) { log.error("Failed to load schema version.", e); - throw new DataSourceInitializationException("Failed to determine database schema version.", e); + throw new ProfileLoadException("Failed to determine database schema version.", e); } log.debug("Database loaded for profile {} has schema version {}.", profileName, loadedSchemaVersion); if (loadedSchemaVersion < SCHEMA_VERSION) { @@ -51,13 +51,13 @@ public class JdbcDataSourceFactory { // TODO: Do migration } else if (loadedSchemaVersion > SCHEMA_VERSION) { log.debug("Schema version {} is higher than the app's version {}. Cannot continue.", loadedSchemaVersion, SCHEMA_VERSION); - throw new DataSourceInitializationException("Profile " + profileName + " has a database with an unsupported schema version."); + throw new ProfileLoadException("Profile " + profileName + " has a database with an unsupported schema version."); } } return new JdbcDataSource(getJdbcUrl(profileName), Profile.getContentDir(profileName)); } - private void createNewDatabase(String profileName) throws DataSourceInitializationException { + private void createNewDatabase(String profileName) throws ProfileLoadException { log.info("Creating new database for profile {}.", profileName); JdbcDataSource dataSource = new JdbcDataSource(getJdbcUrl(profileName), Profile.getContentDir(profileName)); try ( @@ -81,15 +81,15 @@ public class JdbcDataSourceFactory { } catch (IOException e) { log.error("IO Exception when trying to create database.", e); FileUtil.deleteIfPossible(getDatabaseFile(profileName)); - throw new DataSourceInitializationException("Failed to read SQL data to create database schema.", e); + throw new ProfileLoadException("Failed to read SQL data to create database schema.", e); } catch (SQLException e) { log.error("SQL Exception when trying to create database.", e); FileUtil.deleteIfPossible(getDatabaseFile(profileName)); - throw new DataSourceInitializationException("Failed to create the database due to an SQL error.", e); + throw new ProfileLoadException("Failed to create the database due to an SQL error.", e); } if (!testConnection(dataSource)) { FileUtil.deleteIfPossible(getDatabaseFile(profileName)); - throw new DataSourceInitializationException("Testing the database connection failed."); + throw new ProfileLoadException("Testing the database connection failed."); } } @@ -117,7 +117,11 @@ public class JdbcDataSourceFactory { private static int getSchemaVersion(String profileName) throws IOException { if (Files.exists(getSchemaVersionFile(profileName))) { - return Integer.parseInt(Files.readString(getSchemaVersionFile(profileName))); + try { + return Integer.parseInt(Files.readString(getSchemaVersionFile(profileName)).strip()); + } catch (NumberFormatException e) { + throw new IOException("Could not parse integer schema version.", e); + } } else { writeCurrentSchemaVersion(profileName); return SCHEMA_VERSION; diff --git a/src/main/java/com/andrewlalis/perfin/data/util/FileUtil.java b/src/main/java/com/andrewlalis/perfin/data/util/FileUtil.java index 540481d..1d276e5 100644 --- a/src/main/java/com/andrewlalis/perfin/data/util/FileUtil.java +++ b/src/main/java/com/andrewlalis/perfin/data/util/FileUtil.java @@ -37,9 +37,13 @@ public class FileUtil { public static void deleteIfPossible(Path file) { try { - Files.deleteIfExists(file); + if (Files.isDirectory(file)) { + deleteDirRecursive(file); + } else { + Files.deleteIfExists(file); + } } catch (IOException e) { - log.error("Failed to delete file " + file, e); + log.error("Failed to delete " + file, e); } } diff --git a/src/main/java/com/andrewlalis/perfin/model/Profile.java b/src/main/java/com/andrewlalis/perfin/model/Profile.java index dc380c2..7dc8ee9 100644 --- a/src/main/java/com/andrewlalis/perfin/model/Profile.java +++ b/src/main/java/com/andrewlalis/perfin/model/Profile.java @@ -2,8 +2,9 @@ package com.andrewlalis.perfin.model; import com.andrewlalis.perfin.PerfinApp; import com.andrewlalis.perfin.data.DataSource; -import com.andrewlalis.perfin.data.DataSourceInitializationException; +import com.andrewlalis.perfin.data.ProfileLoadException; import com.andrewlalis.perfin.data.impl.JdbcDataSourceFactory; +import com.andrewlalis.perfin.data.util.FileUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -118,17 +119,24 @@ public class Profile { } } - public static void loadLast() throws IOException, DataSourceInitializationException { + public static void loadLast() throws ProfileLoadException { load(getLastProfile()); } - public static void load(String name) throws IOException, DataSourceInitializationException { + public static void load(String name) throws ProfileLoadException { if (Files.notExists(getDir(name))) { - initProfileDir(name); + try { + initProfileDir(name); + } catch (IOException e) { + FileUtil.deleteIfPossible(getDir(name)); + throw new ProfileLoadException("Failed to initialize new profile directory.", e); + } } Properties settings = new Properties(); try (var in = Files.newInputStream(getSettingsFile(name))) { settings.load(in); + } catch (IOException e) { + throw new ProfileLoadException("Failed to load profile settings.", e); } current = new Profile(name, settings, new JdbcDataSourceFactory().getDataSource(name)); saveLastProfile(current.getName()); diff --git a/src/main/java/com/andrewlalis/perfin/view/StartupSplashScreen.java b/src/main/java/com/andrewlalis/perfin/view/StartupSplashScreen.java index 3d2e476..38c94cb 100644 --- a/src/main/java/com/andrewlalis/perfin/view/StartupSplashScreen.java +++ b/src/main/java/com/andrewlalis/perfin/view/StartupSplashScreen.java @@ -66,6 +66,11 @@ public class StartupSplashScreen extends Stage implements Consumer { } catch (Exception e) { accept("Startup failed: " + e.getMessage()); e.printStackTrace(System.err); + try { + Thread.sleep(5000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } Platform.runLater(this::close); return; }