+ Added FileMonitor feature for localization files to allow for active reloading
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
[CommandBenchmark]
|
||||
BenchmarkInfo=
|
||||
BenchmarkInvalid=
|
||||
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=The benchmark operation you were trying to perform was invalid!
|
||||
|
||||
[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
|
||||
|
||||
@@ -12,6 +12,8 @@ import dataStructures.TaggedPairStore;
|
||||
import utils.FileUtils;
|
||||
import utils.GlobalLog;
|
||||
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
|
||||
// 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 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
|
||||
public LocBase(String filename, String functionName)
|
||||
{
|
||||
@@ -39,6 +44,22 @@ public abstract class LocBase
|
||||
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
|
||||
// about localized information that is being looked up.
|
||||
private class LocInfo
|
||||
|
||||
@@ -3,6 +3,7 @@ package core;
|
||||
import java.util.ArrayList;
|
||||
import utils.GlobalLog;
|
||||
import utils.LogFilter;
|
||||
import utils.io.FileMonitor;
|
||||
import dataStructures.Pair;
|
||||
|
||||
// Performs the same localization for the strings associated with command names as
|
||||
@@ -27,6 +28,8 @@ public class LocCommands extends LocBase
|
||||
UpdateLocFromDisk();
|
||||
ScrapeAll();
|
||||
SaveLocToDisk();
|
||||
|
||||
fileMonitor = new FileMonitor(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -47,4 +50,9 @@ public class LocCommands extends LocBase
|
||||
instance.stringStore.ForEach((pair) -> raw.add((String)((Pair<?, ?>)pair).First ));
|
||||
return raw;
|
||||
}
|
||||
|
||||
public static void Upkeep()
|
||||
{
|
||||
instance.Update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package core;
|
||||
|
||||
import utils.GlobalLog;
|
||||
import utils.LogFilter;
|
||||
import utils.io.FileMonitor;
|
||||
|
||||
// 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
|
||||
@@ -26,6 +27,8 @@ public class LocStrings extends LocBase
|
||||
UpdateLocFromDisk();
|
||||
ScrapeAll();
|
||||
SaveLocToDisk();
|
||||
|
||||
fileMonitor = new FileMonitor(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -43,4 +46,9 @@ public class LocStrings extends LocBase
|
||||
{
|
||||
return instance.GetKey(stubbedPreviously);
|
||||
}
|
||||
|
||||
public static void Upkeep()
|
||||
{
|
||||
instance.Update();
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@ import java.util.List;
|
||||
|
||||
import dataStructures.Pair;
|
||||
import utils.FileUtils;
|
||||
import utils.directoryMonitor.DirectoryMonitor;
|
||||
import utils.directoryMonitor.MonitoredFile;
|
||||
import utils.io.DirectoryMonitor;
|
||||
import utils.io.MonitoredFile;
|
||||
|
||||
// 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
|
||||
|
||||
+21
-3
@@ -78,6 +78,9 @@ public class Main extends ListenerAdapter
|
||||
// RP logging system
|
||||
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.
|
||||
// Run plugins right before invoking the commands but after all other setup.
|
||||
if(commandManager.InvokeOnNewThread(guild, channel, user, input, response) == false)
|
||||
@@ -88,8 +91,8 @@ public class Main extends ListenerAdapter
|
||||
response.Call(pluginOutput);
|
||||
}
|
||||
|
||||
// Run any upkeep we need to
|
||||
PerCommandUpkeep();
|
||||
// Run any upkeep in post we need to
|
||||
PerCommandUpkeepPost();
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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();
|
||||
|
||||
// Update command-specific
|
||||
RPManager.Upkeep(kitty);
|
||||
|
||||
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())
|
||||
return new ArrayList<Path>();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
Files.find(Paths.get(startingDir), 999, (path, attributes) -> attributes.isRegularFile()).forEach(items::add);
|
||||
@@ -53,4 +52,20 @@ public class FileUtils
|
||||
|
||||
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.nio.file.Files;
|
||||
@@ -10,6 +10,7 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import utils.FileUtils;
|
||||
import utils.GlobalLog;
|
||||
import utils.LogFilter;
|
||||
|
||||
@@ -17,11 +18,6 @@ import utils.LogFilter;
|
||||
// for external stability and support
|
||||
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
|
||||
private String directory;
|
||||
private ArrayList<MonitoredFile> last;
|
||||
@@ -29,7 +25,7 @@ public class DirectoryMonitor
|
||||
// Constructs a new file monitor and logs initialization
|
||||
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.last = Scrape();
|
||||
@@ -37,22 +33,6 @@ public class DirectoryMonitor
|
||||
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
|
||||
private ArrayList<MonitoredFile> Scrape()
|
||||
{
|
||||
@@ -64,13 +44,13 @@ public class DirectoryMonitor
|
||||
{
|
||||
paths.filter(Files::isRegularFile).forEach((path)->
|
||||
{
|
||||
files.add(new MonitoredFile(path, LastModified(path)));
|
||||
files.add(new MonitoredFile(path, FileUtils.LastModified(path)));
|
||||
});
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Error(e.getMessage());
|
||||
IOLog.Error(e.getMessage());
|
||||
}
|
||||
|
||||
return files;
|
||||
@@ -150,7 +130,7 @@ public class DirectoryMonitor
|
||||
Collections.sort(last);
|
||||
|
||||
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.
|
||||
@@ -163,6 +143,6 @@ public class DirectoryMonitor
|
||||
private void Print(ArrayList<MonitoredFile> toPrint)
|
||||
{
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user