+ Added FileMonitor feature for localization files to allow for active reloading
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[CommandBenchmark]
|
[CommandBenchmark]
|
||||||
BenchmarkInfo=
|
BenchmarkInfo=Allows you to lookup PC component benchmarks from UserBenchmark! You can use `bench find <name-snippet>` to see what's in the database, `bench info <name-snippet>` to look at a specific component, or the experimental `bench compare` commands!
|
||||||
BenchmarkInvalid=
|
BenchmarkInvalid=The benchmark operation you were trying to perform was invalid!
|
||||||
|
|
||||||
[CommandPollManage]
|
[CommandPollManage]
|
||||||
PollManageInfo='start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll
|
PollManageInfo='start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import dataStructures.TaggedPairStore;
|
|||||||
import utils.FileUtils;
|
import utils.FileUtils;
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
import utils.LogFilter;
|
import utils.LogFilter;
|
||||||
|
import utils.io.FileMonitor;
|
||||||
|
import utils.io.MonitoredFile;
|
||||||
|
|
||||||
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
||||||
// generates/updates a file externally with all the stub values as keys that are localized.
|
// generates/updates a file externally with all the stub values as keys that are localized.
|
||||||
@@ -32,6 +34,9 @@ public abstract class LocBase
|
|||||||
private void Warn(String str) { GlobalLog.Warn(LogFilter.Strings, str); }
|
private void Warn(String str) { GlobalLog.Warn(LogFilter.Strings, str); }
|
||||||
private void Error(String str) { GlobalLog.Error(LogFilter.Strings, str); }
|
private void Error(String str) { GlobalLog.Error(LogFilter.Strings, str); }
|
||||||
|
|
||||||
|
// File monitoring
|
||||||
|
protected FileMonitor fileMonitor;
|
||||||
|
|
||||||
// Ok... so this is an array because if it's not an array, the parser will parse the string
|
// Ok... so this is an array because if it's not an array, the parser will parse the string
|
||||||
public LocBase(String filename, String functionName)
|
public LocBase(String filename, String functionName)
|
||||||
{
|
{
|
||||||
@@ -39,6 +44,22 @@ public abstract class LocBase
|
|||||||
this.functionName = functionName;
|
this.functionName = functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks the file specified for updates
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
synchronized(stringStore)
|
||||||
|
{
|
||||||
|
fileMonitor.Update(this::OnFileChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the file is changed
|
||||||
|
protected void OnFileChange(MonitoredFile file)
|
||||||
|
{
|
||||||
|
Log("Loc file was modified at path " + file.path);
|
||||||
|
UpdateLocFromDisk();
|
||||||
|
}
|
||||||
|
|
||||||
// Structure used for holding a pair of strings and any other info we need
|
// Structure used for holding a pair of strings and any other info we need
|
||||||
// about localized information that is being looked up.
|
// about localized information that is being looked up.
|
||||||
private class LocInfo
|
private class LocInfo
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package core;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
import utils.LogFilter;
|
import utils.LogFilter;
|
||||||
|
import utils.io.FileMonitor;
|
||||||
import dataStructures.Pair;
|
import dataStructures.Pair;
|
||||||
|
|
||||||
// Performs the same localization for the strings associated with command names as
|
// Performs the same localization for the strings associated with command names as
|
||||||
@@ -27,6 +28,8 @@ public class LocCommands extends LocBase
|
|||||||
UpdateLocFromDisk();
|
UpdateLocFromDisk();
|
||||||
ScrapeAll();
|
ScrapeAll();
|
||||||
SaveLocToDisk();
|
SaveLocToDisk();
|
||||||
|
|
||||||
|
fileMonitor = new FileMonitor(filename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -47,4 +50,9 @@ public class LocCommands extends LocBase
|
|||||||
instance.stringStore.ForEach((pair) -> raw.add((String)((Pair<?, ?>)pair).First ));
|
instance.stringStore.ForEach((pair) -> raw.add((String)((Pair<?, ?>)pair).First ));
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Upkeep()
|
||||||
|
{
|
||||||
|
instance.Update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package core;
|
|||||||
|
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
import utils.LogFilter;
|
import utils.LogFilter;
|
||||||
|
import utils.io.FileMonitor;
|
||||||
|
|
||||||
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
||||||
// generates/updates a file externally (phrases.config) with all the stub values as keys that
|
// generates/updates a file externally (phrases.config) with all the stub values as keys that
|
||||||
@@ -26,6 +27,8 @@ public class LocStrings extends LocBase
|
|||||||
UpdateLocFromDisk();
|
UpdateLocFromDisk();
|
||||||
ScrapeAll();
|
ScrapeAll();
|
||||||
SaveLocToDisk();
|
SaveLocToDisk();
|
||||||
|
|
||||||
|
fileMonitor = new FileMonitor(filename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -43,4 +46,9 @@ public class LocStrings extends LocBase
|
|||||||
{
|
{
|
||||||
return instance.GetKey(stubbedPreviously);
|
return instance.GetKey(stubbedPreviously);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Upkeep()
|
||||||
|
{
|
||||||
|
instance.Update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import dataStructures.Pair;
|
import dataStructures.Pair;
|
||||||
import utils.FileUtils;
|
import utils.FileUtils;
|
||||||
import utils.directoryMonitor.DirectoryMonitor;
|
import utils.io.DirectoryMonitor;
|
||||||
import utils.directoryMonitor.MonitoredFile;
|
import utils.io.MonitoredFile;
|
||||||
|
|
||||||
// All things considered, this doesn't need to be particularly efficient since anything
|
// All things considered, this doesn't need to be particularly efficient since anything
|
||||||
// less than 10ms of search time won't be noticable to an end user really, not for
|
// less than 10ms of search time won't be noticable to an end user really, not for
|
||||||
|
|||||||
+21
-3
@@ -78,6 +78,9 @@ public class Main extends ListenerAdapter
|
|||||||
// RP logging system
|
// RP logging system
|
||||||
RPManager.instance.addLine(channel, user, input);
|
RPManager.instance.addLine(channel, user, input);
|
||||||
|
|
||||||
|
// Run any pre-emptive upkeep we need to
|
||||||
|
PerCommandUpkeepPre();
|
||||||
|
|
||||||
// Attempt to spin up a command. If the command doesn't exist.
|
// Attempt to spin up a command. If the command doesn't exist.
|
||||||
// Run plugins right before invoking the commands but after all other setup.
|
// Run plugins right before invoking the commands but after all other setup.
|
||||||
if(commandManager.InvokeOnNewThread(guild, channel, user, input, response) == false)
|
if(commandManager.InvokeOnNewThread(guild, channel, user, input, response) == false)
|
||||||
@@ -88,8 +91,8 @@ public class Main extends ListenerAdapter
|
|||||||
response.Call(pluginOutput);
|
response.Call(pluginOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run any upkeep we need to
|
// Run any upkeep in post we need to
|
||||||
PerCommandUpkeep();
|
PerCommandUpkeepPost();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is run on the JDA GuildMessageReceivedEvent before anything else happens.
|
// This is run on the JDA GuildMessageReceivedEvent before anything else happens.
|
||||||
@@ -144,11 +147,26 @@ public class Main extends ListenerAdapter
|
|||||||
|
|
||||||
// This is for stuff that we need to do on a regular basis, but don't
|
// This is for stuff that we need to do on a regular basis, but don't
|
||||||
// necessarily want running at all points in time.
|
// necessarily want running at all points in time.
|
||||||
private static boolean PerCommandUpkeep()
|
// Happens just after the command / plugin runs.
|
||||||
|
private static boolean PerCommandUpkeepPost()
|
||||||
{
|
{
|
||||||
|
// Upkeep database
|
||||||
databaseManager.Upkeep();
|
databaseManager.Upkeep();
|
||||||
|
|
||||||
|
// Update command-specific
|
||||||
RPManager.Upkeep(kitty);
|
RPManager.Upkeep(kitty);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only called once per command. Good for lazily updating.
|
||||||
|
// Happens just before the command / plugin runs.
|
||||||
|
private static boolean PerCommandUpkeepPre()
|
||||||
|
{
|
||||||
|
// Upkeep localization system's file monitoring
|
||||||
|
LocStrings.Upkeep();
|
||||||
|
LocCommands.Upkeep();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,6 @@ public class FileUtils
|
|||||||
if(!tmpDir.exists())
|
if(!tmpDir.exists())
|
||||||
return new ArrayList<Path>();
|
return new ArrayList<Path>();
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Files.find(Paths.get(startingDir), 999, (path, attributes) -> attributes.isRegularFile()).forEach(items::add);
|
Files.find(Paths.get(startingDir), 999, (path, attributes) -> attributes.isRegularFile()).forEach(items::add);
|
||||||
@@ -53,4 +52,20 @@ public class FileUtils
|
|||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check when a file was last modified by path
|
||||||
|
public static Long LastModified(Path path)
|
||||||
|
{
|
||||||
|
File file = new File(path.toString());
|
||||||
|
|
||||||
|
if(file.exists())
|
||||||
|
{
|
||||||
|
return file.lastModified();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GlobalLog.Error(LogFilter.Util, "File doesn't exist at path: " + path);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-27
@@ -1,4 +1,4 @@
|
|||||||
package utils.directoryMonitor;
|
package utils.io;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -10,6 +10,7 @@ import java.util.List;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import utils.FileUtils;
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
import utils.LogFilter;
|
import utils.LogFilter;
|
||||||
|
|
||||||
@@ -17,11 +18,6 @@ import utils.LogFilter;
|
|||||||
// for external stability and support
|
// for external stability and support
|
||||||
public class DirectoryMonitor
|
public class DirectoryMonitor
|
||||||
{
|
{
|
||||||
// Logging
|
|
||||||
private void Log(String s) { GlobalLog.Log(LogFilter.Util, s); }
|
|
||||||
private void Warn(String s) { GlobalLog.Warn(LogFilter.Util, s); }
|
|
||||||
private void Error(String s) { GlobalLog.Error(LogFilter.Util, s); }
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
private String directory;
|
private String directory;
|
||||||
private ArrayList<MonitoredFile> last;
|
private ArrayList<MonitoredFile> last;
|
||||||
@@ -29,7 +25,7 @@ public class DirectoryMonitor
|
|||||||
// Constructs a new file monitor and logs initialization
|
// Constructs a new file monitor and logs initialization
|
||||||
public DirectoryMonitor(String directory)
|
public DirectoryMonitor(String directory)
|
||||||
{
|
{
|
||||||
Log("Reading directory files for montioring in: " + directory.toString());
|
IOLog.Log("Reading directory files for montioring in: " + directory.toString());
|
||||||
|
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
this.last = Scrape();
|
this.last = Scrape();
|
||||||
@@ -37,22 +33,6 @@ public class DirectoryMonitor
|
|||||||
Print(last);
|
Print(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check when a file was last modified by path
|
|
||||||
private Long LastModified(Path path)
|
|
||||||
{
|
|
||||||
File file = new File(path.toString());
|
|
||||||
|
|
||||||
if(file.exists())
|
|
||||||
{
|
|
||||||
return file.lastModified();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Error("File looking for doesn't exist for directory monitor at path: " + path);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scrape the target directory for all files and store them as custom objects in the list
|
// Scrape the target directory for all files and store them as custom objects in the list
|
||||||
private ArrayList<MonitoredFile> Scrape()
|
private ArrayList<MonitoredFile> Scrape()
|
||||||
{
|
{
|
||||||
@@ -64,13 +44,13 @@ public class DirectoryMonitor
|
|||||||
{
|
{
|
||||||
paths.filter(Files::isRegularFile).forEach((path)->
|
paths.filter(Files::isRegularFile).forEach((path)->
|
||||||
{
|
{
|
||||||
files.add(new MonitoredFile(path, LastModified(path)));
|
files.add(new MonitoredFile(path, FileUtils.LastModified(path)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
Error(e.getMessage());
|
IOLog.Error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
@@ -150,7 +130,7 @@ public class DirectoryMonitor
|
|||||||
Collections.sort(last);
|
Collections.sort(last);
|
||||||
|
|
||||||
if(last.size() == 0)
|
if(last.size() == 0)
|
||||||
Warn("There's nothing at all in a FileMonitor's target folder! Folder: " + directory);
|
IOLog.Warn("There's nothing at all in a FileMonitor's target folder! Folder: " + directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current list of files the monitor is tracking in the directory.
|
// Returns the current list of files the monitor is tracking in the directory.
|
||||||
@@ -163,6 +143,6 @@ public class DirectoryMonitor
|
|||||||
private void Print(ArrayList<MonitoredFile> toPrint)
|
private void Print(ArrayList<MonitoredFile> toPrint)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < toPrint.size(); ++i)
|
for(int i = 0; i < toPrint.size(); ++i)
|
||||||
Log(toPrint.get(i).path.toString());
|
IOLog.Log(toPrint.get(i).path.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package utils.io;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import utils.FileUtils;
|
||||||
|
|
||||||
|
// Monitors a single file for changes - the file must exist and is expected to continue to exist.
|
||||||
|
public class FileMonitor
|
||||||
|
{
|
||||||
|
MonitoredFile file;
|
||||||
|
|
||||||
|
// Constructs file monitor for a given file at a specific path.
|
||||||
|
public FileMonitor(String path)
|
||||||
|
{
|
||||||
|
Long last = FileUtils.LastModified(Paths.get(path));
|
||||||
|
|
||||||
|
if(last == null)
|
||||||
|
{
|
||||||
|
file = null;
|
||||||
|
IOLog.Error("Couldn't find a readable file at " + path + "!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file = new MonitoredFile(Paths.get(path), last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looks at the file and sees if it has undergone any changes.
|
||||||
|
// If so, the fileChanged function provided is called!
|
||||||
|
public void Update(Consumer<? super MonitoredFile> fileChanged)
|
||||||
|
{
|
||||||
|
if(file == null)
|
||||||
|
{
|
||||||
|
IOLog.Error("Attempted to update a file that doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long last = FileUtils.LastModified(file.path);
|
||||||
|
if(last == null)
|
||||||
|
{
|
||||||
|
IOLog.Error("The file previously at " + file.path + " couldn't be read!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(last.longValue() != file.lastModified.longValue())
|
||||||
|
{
|
||||||
|
IOLog.Log("Most recently modified at " + last + ", stored version at " + file.lastModified);
|
||||||
|
file = new MonitoredFile(file.path, last);
|
||||||
|
fileChanged.accept(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package utils.io;
|
||||||
|
|
||||||
|
import utils.GlobalLog;
|
||||||
|
import utils.LogFilter;
|
||||||
|
|
||||||
|
// Logging shim
|
||||||
|
public class IOLog
|
||||||
|
{
|
||||||
|
public static void Log(String s) { GlobalLog.Log(LogFilter.Util, s); }
|
||||||
|
public static void Warn(String s) { GlobalLog.Warn(LogFilter.Util, s); }
|
||||||
|
public static void Error(String s) { GlobalLog.Error(LogFilter.Util, s); }
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package utils.directoryMonitor;
|
package utils.io;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
Reference in New Issue
Block a user