diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/DatabaseUpdater.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/DatabaseUpdater.java
index 98c14c3aa..9b6b4f526 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/sql/DatabaseUpdater.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/DatabaseUpdater.java
@@ -20,19 +20,17 @@
package com.seibel.distanthorizons.core.sql;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
-import com.seibel.distanthorizons.core.util.ResourceUtil;
import org.apache.logging.log4j.Logger;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.sql.BatchUpdateException;
+import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Map;
-import java.util.Stack;
+import java.util.Scanner;
+/** Handles both initial setup and updating of the sql databases. */
public class DatabaseUpdater
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -41,22 +39,24 @@ public class DatabaseUpdater
/** Since java can only run one sql query at a time this string is used to split up our scripts into individual queries. */
public static final String UPDATE_SCRIPT_BATCH_SEPARATOR = "--batch--";
+ private static final String SQL_SCRIPT_RESOURCE_FOLDER = "sqlScripts/";
+ /**
+ * Unfortunately dynamically pulling in resource files is very unstable in Java so we need a file that lists all the scripts to expect.
+ * (If anyone has a good way to automatically pull all resource files ending in `.sql` instead, please replace the existing code.)
+ */
+ private static final String SQL_SCRIPT_LIST_FILE = SQL_SCRIPT_RESOURCE_FOLDER+"scriptList.txt";
- /** Handles both initial setup and */
+
+ //================//
+ // script running //
+ //================//
+
public static void runAutoUpdateScripts(AbstractDhRepo repo) throws SQLException
{
// get the resource scripts
- ArrayList sqlScripts;
- try
- {
- sqlScripts = ResourceUtil.getFilesInFolder("sqlScripts", ".sql");
- }
- catch (URISyntaxException | IOException e)
- {
- // shouldn't normally happen, but just in case
- throw new RuntimeException(e);
- }
+ ArrayList scriptList = getAutoUpdateScripts();
+
// create the base update table if necessary
@@ -75,7 +75,7 @@ public class DatabaseUpdater
// attempt to run any new update scripts
- for (ResourceUtil.ResourceFile resource : sqlScripts)
+ for (SqlScript resource : scriptList)
{
Map scriptAlreadyRunResult = repo.queryDictionaryFirst("SELECT EXISTS(SELECT 1 FROM "+SCHEMA_TABLE_NAME+" WHERE ScriptName='"+resource.name+"') as 'existingCount';");
if (scriptAlreadyRunResult != null && (int) scriptAlreadyRunResult.get("existingCount") == 0)
@@ -87,7 +87,7 @@ public class DatabaseUpdater
try
{
// split up each individual statement so Java can handle the script as a whole
- String[] fileUpdateSqlArray = resource.content.split(UPDATE_SCRIPT_BATCH_SEPARATOR);
+ String[] fileUpdateSqlArray = resource.queryString.split(UPDATE_SCRIPT_BATCH_SEPARATOR);
Connection connection = repo.getConnection();
try (Statement statement = connection.createStatement())
@@ -137,7 +137,7 @@ public class DatabaseUpdater
// updating needs to stop to prevent data corruption
LOGGER.error("Unexpected error running database update script ["+resource.name+"] on database ["+repo.databaseLocation+"], stopping database update. Database reading/writing may fail if you continue. \n" +
"Error: ["+e.getMessage()+"]. \n" +
- "Sql Script:["+resource.content+"]", e);
+ "Sql Script:["+resource.queryString+"]", e);
throw e;
}
@@ -148,4 +148,73 @@ public class DatabaseUpdater
}
}
+
+
+ //===============//
+ // file handling //
+ //===============//
+
+ /** @throws NullPointerException if any of the script files failed to be read. */
+ private static ArrayList getAutoUpdateScripts() throws NullPointerException
+ {
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+
+ // get the script list
+ InputStream scriptListInputStream = loader.getResourceAsStream(SQL_SCRIPT_LIST_FILE);
+ if (scriptListInputStream == null)
+ {
+ throw new NullPointerException("Failed to find the SQL Script list file ["+SQL_SCRIPT_LIST_FILE+"], no auto update scripts can be run.");
+ }
+ Scanner scanner = new Scanner(scriptListInputStream).useDelimiter("\\A");
+ String result = scanner.hasNext() ? scanner.next() : "";
+
+
+
+ // get each script
+ ArrayList scriptList = new ArrayList<>();
+ String[] sqlScriptNames = result.split("\n");
+ for (String scriptName : sqlScriptNames)
+ {
+ scriptName = scriptName.trim();
+ if (scriptName.isEmpty())
+ {
+ // ignore any empty lines
+ continue;
+ }
+ scriptName = SQL_SCRIPT_RESOURCE_FOLDER + scriptName.trim();
+
+ // get the script's content
+ InputStream scriptInputStream = loader.getResourceAsStream(scriptName);
+ if (scriptInputStream == null)
+ {
+ throw new NullPointerException("Failed to find the SQL Script file ["+scriptName+"], no auto update scripts can be run.");
+ }
+ scanner = new Scanner(scriptInputStream).useDelimiter("\\A");
+ result = scanner.hasNext() ? scanner.next() : "";
+
+ scriptList.add(new SqlScript(scriptName, result));
+ }
+
+ return scriptList;
+ }
+
+
+
+ //================//
+ // helper classes //
+ //================//
+
+ private static class SqlScript
+ {
+ public String name;
+ public String queryString;
+
+ public SqlScript(String name, String queryString)
+ {
+ this.name = name;
+ this.queryString = queryString;
+ }
+ }
+
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/ResourceUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/ResourceUtil.java
deleted file mode 100644
index 275708dfd..000000000
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/ResourceUtil.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * This file is part of the Distant Horizons mod
- * licensed under the GNU LGPL v3 License.
- *
- * Copyright (C) 2020-2023 James Seibel
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.seibel.distanthorizons.core.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-public class ResourceUtil
-{
- /**
- * Returns all files in the "resources" folders. getFilesInFolder(String directoryName, String fileExtension) throws URISyntaxException, IOException
- {
- ArrayList resourceFiles = new ArrayList<>();
-
- URL url = Thread.currentThread().getContextClassLoader().getResource(directoryName);
- if (url != null)
- {
- if (url.getProtocol().equals("file"))
- {
- File rootFile = Paths.get(url.toURI()).toFile();
- File[] files = rootFile.listFiles();
- if (files != null)
- {
- for (File file : files)
- {
- if (file.getName().endsWith(fileExtension))
- {
- String content = FileUtil.readFile(file, Charset.defaultCharset());
- ResourceFile resourceFile = new ResourceFile(file.getName(), content);
- resourceFiles.add(resourceFile);
- }
- }
- }
- }
- else if (url.getProtocol().equals("jar"))
- {
- String dirname = directoryName + "/";
- String path = url.getPath();
- String jarPath = path.substring(5, path.indexOf("!"));
- try (JarFile jar = new JarFile(URLDecoder.decode(jarPath, StandardCharsets.UTF_8.name())))
- {
- Enumeration entries = jar.entries();
- while (entries.hasMoreElements())
- {
- JarEntry entry = entries.nextElement();
- String fileName = entry.getName();
- if (fileName.startsWith(dirname) && !dirname.equals(fileName))
- {
- if (fileName.endsWith(fileExtension))
- {
- URL resource = Thread.currentThread().getContextClassLoader().getResource(fileName);
- File file = new File(resource.getFile());
- String content = FileUtil.readFile(file, Charset.defaultCharset());
-
- ResourceFile resourceFile = new ResourceFile(file.getName(), content);
- resourceFiles.add(resourceFile);
- }
- }
- }
- }
- }
- }
-
- return resourceFiles;
- }
-
-
-
- //==============//
- // helper class //
- //==============//
-
- public static class ResourceFile
- {
- public final String name;
- public final String content;
-
- public ResourceFile(String name, String content)
- {
- this.name = name;
- this.content = content;
- }
- }
-
-}
diff --git a/core/src/main/resources/sqlScripts/0010-sqlite-createFullDataTable.sql b/core/src/main/resources/sqlScripts/0010-sqlite-createInitialDataTables.sql
similarity index 100%
rename from core/src/main/resources/sqlScripts/0010-sqlite-createFullDataTable.sql
rename to core/src/main/resources/sqlScripts/0010-sqlite-createInitialDataTables.sql
diff --git a/core/src/main/resources/sqlScripts/readme.md b/core/src/main/resources/sqlScripts/readme.md
index 4dea66089..18fdb2456 100644
--- a/core/src/main/resources/sqlScripts/readme.md
+++ b/core/src/main/resources/sqlScripts/readme.md
@@ -6,6 +6,12 @@ https://dbup.readthedocs.io/en/latest/philosophy-behind-dbup/
+### Adding New Scripts:
+New scripts must be added to the "scriptList.txt" file, otherwise they will not be run.
+(If anyone has a good way to automatically pull all resource files ending in `.sql` instead, please let us know.)
+
+
+
### File Naming:
- The first 3 numbers are major scripts.
- The 4th number is for minor/related scripts or if a bug fix needs to be applied between scripts.
@@ -31,3 +37,6 @@ CREATE TABLE TableTwo(
,Data BLOB NULL
);
```
+
+
+
diff --git a/core/src/main/resources/sqlScripts/scriptList.txt b/core/src/main/resources/sqlScripts/scriptList.txt
new file mode 100644
index 000000000..47c749378
--- /dev/null
+++ b/core/src/main/resources/sqlScripts/scriptList.txt
@@ -0,0 +1,2 @@
+
+0010-sqlite-createInitialDataTables.sql