Fixed message store. Enabled writing indirect configuration values to files.

This commit is contained in:
Sandy Mossgrave 2024-10-05 15:20:55 -07:00
parent dc9ac7eddd
commit eb4d64d189
3 changed files with 240 additions and 106 deletions

View File

@ -31,34 +31,23 @@ import java.util.prefs.Preferences;
/** /**
* "Ms Merry," you may say, "You literally import the Preferences class, and yet * "Ms Merry," you may say, "You literally import the Preferences class, and yet
* you insist on writing your own configuration store. Why?" "Iunno," I reply. * you insist on writing your own configuration store. Why?" I reply, "Iunno."
* *
* @author sandy * @author sandy
*/ */
public class Configuration { public class Configuration {
private static String CONFIG_FILE_LOCATION = null; private static String CONFIG_FILE_LOCATION = null;
private static Path WORKING_DIR = null;
public static final String CONFIG_FILE_KEY = "PRIESTESS_CONFIG"; public static final String CONFIG_FILE_KEY = "PRIESTESS_CONFIG";
public static final Properties props = System.getProperties();
public static final Preferences prefs = Preferences.userNodeForPackage(Configuration.class); public static final Preferences prefs = Preferences.userNodeForPackage(Configuration.class);
public static final String DEFAULT_CONFIG_FILE_NAME = "priestessconfig.txt"; public static final String DEFAULT_CONFIG_FILE_NAME = "priestessconfig.txt";
private static HashMap<String, String> configuration = new HashMap<>(); private static HashMap<String, StringOrIndirect> configuration = new HashMap<>();
private static final Logger log = Logger.getLogger(Configuration.class.getName()); private static final Logger log = Logger.getLogger(Configuration.class.getName());
public static String findConfigurationFilePath() {
if (getCONFIG_FILE_LOCATION() != null) {
return getCONFIG_FILE_LOCATION();
}
setCONFIG_FILE_LOCATION(findOrCreateConfigurationFile(), false);
return getCONFIG_FILE_LOCATION();
}
private static String findOrCreateConfigurationFile() { private static String findOrCreateConfigurationFile() {
/*
* Try the environment variable
*/
JOptionPane.showConfirmDialog(null, "Select where cult files will be stored."); JOptionPane.showConfirmDialog(null, "Select where cult files will be stored.");
JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess"); JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess");
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
@ -67,8 +56,8 @@ public class Configuration {
while (!approved) { while (!approved) {
rv = jfc.showDialog(null, "Select"); rv = jfc.showDialog(null, "Select");
if (rv == JFileChooser.APPROVE_OPTION) { if (rv == JFileChooser.APPROVE_OPTION) {
File f = jfc.getSelectedFile(); File f = resolveDirectoryToConfigFile(jfc.getSelectedFile());
if (f.isDirectory() && f.canRead() && f.canWrite()) { if (f.canRead() && f.canWrite()) {
prefs.put(CONFIG_FILE_KEY, f.getAbsolutePath()); prefs.put(CONFIG_FILE_KEY, f.getAbsolutePath());
try { try {
prefs.flush(); prefs.flush();
@ -85,22 +74,39 @@ public class Configuration {
return ""; return "";
} }
public static final String FILE_MARKER = "(file)"; public static Path findFileInConfigurationDirectory(Path a, Path p) {
a = a.normalize();
public static String resolveIndirectConfigurationValue(String v) { Path p1 = a.resolveSibling(p);
log.log(Level.INFO, "Index of <" + FILE_MARKER + "> in <" + v + "> is " + v.indexOf(FILE_MARKER)); log.log(Level.INFO, "Resolving {0} against {1} to get {2}", new Object[] { p, a, p1 });
if (v.indexOf(FILE_MARKER) == 0) { if (p1.normalize().startsWith(a.getParent())) {
String relpath = v.substring(FILE_MARKER.length()).trim(); return p1;
File configFile = Paths.get(CONFIG_FILE_LOCATION).toFile();
String configDir;
if (configFile.isDirectory()) {
configDir = configFile.getPath();
} else { } else {
configDir = configFile.getParent(); return null;
}
} }
Path indirectValuePath = Paths.get(configDir, relpath); public static Path findFileInConfigurationDirectory(Path p) {
return findFileInConfigurationDirectory(pathCONFIG_FILE_LOCATION(), p);
}
public static final String FILE_MARKER = "(file)";
public static String resolveIndirectConfigurationValue(String v, File configfile) throws FileNotFoundException {
if (configfile == null) {
throw new FileNotFoundException(
String.format("Could not resolve indirect value {0} against configuration file {1}",
new Object[] { v, configfile }));
}
log.log(Level.INFO, "Index of <" + FILE_MARKER + "> in <" + v + "> is " + v.indexOf(FILE_MARKER));
String relpath;
if (v.contains(FILE_MARKER)) {
relpath = v.substring(v.indexOf(FILE_MARKER) + FILE_MARKER.length());
} else {
relpath = v;
}
relpath = relpath.trim();
Path indirectValuePath = findFileInConfigurationDirectory(configfile.toPath(), Paths.get(relpath));
try (BufferedReader br = new BufferedReader(new FileReader(indirectValuePath.toFile()));) { try (BufferedReader br = new BufferedReader(new FileReader(indirectValuePath.toFile()));) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
br.lines().forEach((s) -> { br.lines().forEach((s) -> {
@ -110,23 +116,36 @@ public class Configuration {
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE,
"Error loading indirect configuration value from (" + indirectValuePath.toString() + ") {0}", "Error loading indirect configuration value from (" + indirectValuePath.toString() + ") {0}", ex);
ex);
} catch (IOException e) { } catch (IOException e) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE,
"Error loading indirect configuration value from (" + indirectValuePath.toString() + ") {0}", "Error loading indirect configuration value from (" + indirectValuePath.toString() + ") {0}", e);
e);
}
} }
return v; return v;
} }
private static final String delimiter = ": "; private static final String delimiter = ": ";
/**
* If given file is a directory, look for the default configuration filename in
* the given directory
*
* @param f The configuration file, or a directory containing the default one.
* @return
*/
private static File resolveDirectoryToConfigFile(File f) { private static File resolveDirectoryToConfigFile(File f) {
if (f.isDirectory()) { if (f.isDirectory()) {
f = Paths.get(f.getPath(), Configuration.DEFAULT_CONFIG_FILE_NAME).toFile(); f = Paths.get(f.getPath(), Configuration.DEFAULT_CONFIG_FILE_NAME).toFile();
try {
if (f.createNewFile()) {
log.log(Level.INFO, "Creating new configuration file in provided directory.");
} else {
log.log(Level.FINEST, "Using default-named configuration file in provided directory.");
}
} catch (IOException e) {
log.log(Level.SEVERE, "Could not create a configuration file in the specified directory {0}: {1}",
new Object[] { f, e.toString() });
}
} }
return f; return f;
} }
@ -134,29 +153,25 @@ public class Configuration {
/** /**
* *
*/ */
public static boolean readConfigurationFromFile(String path) throws IOException { private static boolean readConfigurationFromFile(String path) throws IOException {
if (path == null || path.isBlank()) { if (path == null || path.isBlank()) {
return false; return false;
} }
File f = Paths.get(path).toFile(); File f = resolveDirectoryToConfigFile(new File(path));
if (CONFIG_FILE_LOCATION == null) {
findOrCreateConfigurationFile();
}
f = resolveDirectoryToConfigFile(f);
try (BufferedReader br = new BufferedReader(new FileReader(f))) { try (BufferedReader br = new BufferedReader(new FileReader(f))) {
br.lines().forEach((s) -> { br.lines().forEach((s) -> {
String key = s.substring(0, s.indexOf(delimiter)); String key = s.substring(0, s.indexOf(delimiter));
if (s.length() == s.indexOf(delimiter) + delimiter.length()) { try {
log.log(Level.FINE, "read empty value for key (" + key + ") from configuration file"); configuration.put(key, new StringOrIndirect(s, f));
configuration.put(key, ""); } catch (FileNotFoundException fnfe) {
} else { log.log(Level.SEVERE,
String value = s.substring(s.indexOf(delimiter) + delimiter.length()); "Unable to resolve indirect configuration value against configuration directory."
value = resolveIndirectConfigurationValue(value); + "This should never occur? {0}",
configuration.put(key, value); fnfe);
} }
}); });
CONFIG_FILE_LOCATION = f.toString(); setCONFIG_FILE_LOCATION(f.toString(), true);
return true; return true;
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
return false; return false;
@ -166,12 +181,14 @@ public class Configuration {
public static void findAndReadConfigurationFile() { public static void findAndReadConfigurationFile() {
try { try {
if (readConfigurationFromFile(System.getenv(CONFIG_FILE_KEY))) { if (readConfigurationFromFile(System.getenv(CONFIG_FILE_KEY))) {
return; log.log(Level.FINE, "Using environment variable to locate configuration file");
} else if (readConfigurationFromFile(props.getProperty(CONFIG_FILE_KEY, ""))) {
return; return;
} else if (readConfigurationFromFile(prefs.get(CONFIG_FILE_KEY, ""))) { } else if (readConfigurationFromFile(prefs.get(CONFIG_FILE_KEY, ""))) {
log.log(Level.FINE, "Using package preferences to locate configuration file");
return; return;
} else if (readConfigurationFromFile(findOrCreateConfigurationFile())) { } else if (readConfigurationFromFile(findOrCreateConfigurationFile())) {
log.log(Level.FINE, "Using interactive dialogue to locate configuration file");
return;
} else { } else {
log.log(Level.WARNING, "Could not resolve a configuration file path, using defaults."); log.log(Level.WARNING, "Could not resolve a configuration file path, using defaults.");
} }
@ -188,13 +205,16 @@ public class Configuration {
return CONFIG_FILE_LOCATION; return CONFIG_FILE_LOCATION;
} }
public static Path pathCONFIG_FILE_LOCATION() {
return Paths.get(CONFIG_FILE_LOCATION);
}
/** /**
* @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set * @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set
*/ */
public static void setCONFIG_FILE_LOCATION(String aCONFIG_FILE_LOCATION, boolean persistent) { public static void setCONFIG_FILE_LOCATION(String aCONFIG_FILE_LOCATION, boolean persistent) {
CONFIG_FILE_LOCATION = aCONFIG_FILE_LOCATION; CONFIG_FILE_LOCATION = resolveDirectoryToConfigFile(new File(aCONFIG_FILE_LOCATION)).getAbsolutePath();
if (persistent) { if (persistent) {
props.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
prefs.put(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION); prefs.put(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
try { try {
prefs.flush(); prefs.flush();
@ -207,25 +227,28 @@ public class Configuration {
} }
public static void setConfigurationParameter(String key, String value) { public static void setConfigurationParameter(String key, String value) throws FileNotFoundException {
configuration.put(key, value); configuration.put(key, new StringOrIndirect(value, null));
} }
public static String getConfigurationParameter(String key) { public static String getConfigurationParameter(String key) {
if (configuration.containsKey(key)) { if (configuration.containsKey(key)) {
return configuration.get(key); return configuration.get(key).value;
} else { } else {
configuration.put(key, "");
return ""; return "";
} }
} }
public static void commitConfigurationToFile() { public static void commitConfigurationToFile() {
commitConfigurationToFile(Paths.get(getCONFIG_FILE_LOCATION()));
}
public static void commitConfigurationToFile(Path p) {
Path bkupPath = Paths.get(p.toString() + "bkup");
try { try {
Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.deleteIfExists(bkupPath);
try { try {
Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.copy(p, bkupPath);
} catch (IOException ioe) { } catch (IOException ioe) {
if (ioe instanceof NoSuchFileException) { if (ioe instanceof NoSuchFileException) {
log.log(Level.FINE, "No existing configuration file--not creating backup"); log.log(Level.FINE, "No existing configuration file--not creating backup");
@ -240,12 +263,12 @@ public class Configuration {
"Making backup configuration file failed. Exiting without committing configuration to file"); "Making backup configuration file failed. Exiting without committing configuration to file");
return; return;
} }
File f = Paths.get(CONFIG_FILE_LOCATION).toFile(); File f = resolveDirectoryToConfigFile(p.toFile());
f = resolveDirectoryToConfigFile(f); log.log(Level.FINE, "Committing configuration to {0}", p.toString());
try (BufferedWriter br = new BufferedWriter(new FileWriter(f, false))) { try (BufferedWriter br = new BufferedWriter(new FileWriter(f, false))) {
configuration.forEach((key, value) -> { configuration.forEach((key, value) -> {
try { try {
br.append(key + delimiter + value + "\n"); br.append(key + delimiter + value.toRecord(f) + "\n");
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
} }
@ -296,4 +319,86 @@ public class Configuration {
} }
} }
public static class StringOrIndirect {
public String value;
public String path;
public StringOrIndirect() {
value = "";
}
public StringOrIndirect(String source, File configfile) throws FileNotFoundException {
if (configfile == null) {
Path p = pathCONFIG_FILE_LOCATION();
if (p != null) {
configfile = p.toFile();
} else {
configfile = null;
}
}
if (source.contains(delimiter)) {
if (source.length() == source.indexOf(delimiter) + delimiter.length()) {
String key = source.substring(0, source.indexOf(delimiter));
log.log(Level.FINE, "read empty value for key (" + key + ") from configuration file");
value = "";
} else {
}
source = source.substring(source.indexOf(delimiter) + delimiter.length());
}
// After this point the 'source' string should only contain an immediate value
// or a (file) abc.xyz record
if (source.contains(FILE_MARKER)) {
path = source.substring(source.indexOf(FILE_MARKER) + FILE_MARKER.length()).trim();
value = resolveIndirectConfigurationValue(source, configfile);
} else {
value = source;
}
}
private boolean immediate() {
return path == null;
}
/**
* Converts this to a record in a configuration file. If indirect, commits its
* value to the indirect file.
*
* @return
*/
public String toRecord(File f) {
if (immediate()) {
return value;
} else {
try (BufferedWriter br = new BufferedWriter(new FileWriter(
findFileInConfigurationDirectory(f.toPath(), Paths.get(path)).toFile(), false))) {
br.append(value);
br.flush();
br.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
}
return FILE_MARKER + path;
}
}
@Override
public String toString() {
return value;
}
public String toDebugString() {
if (immediate()) {
return String.format("StringOrIndirect ({0})", value);
} else {
return String.format("StringOrIndirect from {1}: ({0})", value, path);
}
}
}
} }

View File

@ -19,11 +19,14 @@ import java.util.logging.Logger;
/** /**
* OH IT STORES THE PROPHECIES * OH IT STORES THE PROPHECIES
* *
* The configuration file (priestessconfig.txt) contains a key, 'messages', for which the value is a path to the messages store. * The configuration file (priestessconfig.txt) contains a key, 'messages', for
* The messages store contains prophecies that are given every few bean goose invocations. * which the value is a path to the messages store. The messages store contains
* This class first loads the file, scans it and generates a list of indices for the messages it contains. * prophecies that are given every few bean goose invocations. This class first
* loads the file, scans it and generates a list of indices for the messages it
* contains.
* *
* This class could definitely use a cache of the message starts--a special block at the beginning/end of the file with a list of message starts/ends, * This class could definitely use a cache of the message starts--a special
* block at the beginning/end of the file with a list of message starts/ends,
* but I'm not up to writing that today - 7 May 2023 * but I'm not up to writing that today - 7 May 2023
* *
* @author atomb * @author atomb
@ -42,15 +45,30 @@ public class MessageStore {
private boolean messagesCached = false; private boolean messagesCached = false;
private long loadStart = Long.MAX_VALUE; private long loadStart = Long.MAX_VALUE;
public MessageStore(File f1) throws FileNotFoundException, IOException { private Logger log = Logger.getLogger(MessageStore.class.getName());
public MessageStore(File f1) {
log.log(Level.INFO, "loading message store from {0}", f1);
if (f1 == null) {
log.log(Level.WARNING, "Message store not given, initializing blank one");
messagestarts = new int[] {};
} else {
try {
f1 = Configuration.findFileInConfigurationDirectory(f1.toPath()).toFile();
loadStart = System.nanoTime(); loadStart = System.nanoTime();
f = new RandomAccessFile(f1.getPath(), "r"); f = new RandomAccessFile(f1.getPath(), "r");
System.out.println("Message store is " + f.length() + " bytes long"); log.log(Level.FINE, "Message store is {0} bytes long", f.length());
fr = f.getChannel(); fr = f.getChannel();
filelength = f.length(); filelength = f.length();
mc = new MessageCacher(); mc = new MessageCacher();
t = new Thread(mc); t = new Thread(mc);
t.start(); t.start();
log.log(Level.FINE, "Loading message store at {0}", f);
} catch (IOException fnfe) {
log.log(Level.WARNING, "Unable to open message store, initializing blank one {0}", fnfe);
messagestarts = new int[] {};
}
}
} }
public String messageAt(int i) { public String messageAt(int i) {
@ -83,6 +101,9 @@ public class MessageStore {
} }
public String randomMessage() { public String randomMessage() {
if (messagestarts == null || messagestarts.length == 0) {
return null;
}
return messageAt((int) (messagestarts.length * Math.random())); return messageAt((int) (messagestarts.length * Math.random()));
} }
@ -135,7 +156,7 @@ public class MessageStore {
messagestarts[i] = messagestarts1[i].intValue(); messagestarts[i] = messagestarts1[i].intValue();
} }
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex); log.log(Level.SEVERE, null, ex);
} }
for (int i : messagestarts) { for (int i : messagestarts) {
System.out.println("Found invocation message at position " + i); System.out.println("Found invocation message at position " + i);

View File

@ -26,6 +26,7 @@ import discord4j.discordjson.json.ApplicationCommandRequest;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -89,7 +90,7 @@ public class Priestess {
public static final String MESSAGES = "messages"; public static final String MESSAGES = "messages";
public static final String TESTSUITE = "testsuite"; public static final String TESTSUITE = "testsuite";
private MessageStore ms = null; private MessageStore ms = new MessageStore(null);
public static final String DEBUG_LEVEL = "debug_level"; public static final String DEBUG_LEVEL = "debug_level";
@ -132,12 +133,21 @@ public class Priestess {
break; break;
case "debug-level": case "debug-level":
String newlevel = args[i].substring(args[i].indexOf('=') + 1); String newlevel = args[i].substring(args[i].indexOf('=') + 1);
try {
Configuration.setConfigurationParameter(DEBUG_LEVEL, newlevel); Configuration.setConfigurationParameter(DEBUG_LEVEL, newlevel);
} catch (FileNotFoundException fnfe) {
log.log(Level.SEVERE, "Could not resolve debug level from given file? {0}", fnfe);
}
trySetDebugLevel(newlevel); trySetDebugLevel(newlevel);
i++; i++;
break; break;
case "debug": case "debug":
try {
Configuration.setConfigurationParameter(DEBUG_LEVEL, Level.ALL.toString()); Configuration.setConfigurationParameter(DEBUG_LEVEL, Level.ALL.toString());
} catch (FileNotFoundException fnfe) {
log.log(Level.SEVERE,
"Could not resolve debug level from given file? This should never happen. {0}", fnfe);
}
trySetDebugLevel(yarg); trySetDebugLevel(yarg);
i++; i++;
break; break;
@ -351,18 +361,19 @@ public class Priestess {
return Mono.empty(); return Mono.empty();
}).subscribe(); }).subscribe();
//dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot()) // dc.on(MessageCreateEvent.class).filter(event ->
//.filter(g -> !g.getGuild().blockOptional().isEmpty()).flatMap(guildedmessagehandler).subscribe(); // !event.getMessage().getAuthor().get().isBot())
// .filter(g ->
// !g.getGuild().blockOptional().isEmpty()).flatMap(guildedmessagehandler).subscribe();
dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot()) dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot())
/*.filter(g -> g.getGuild().blockOptional().isEmpty())*/.flatMap(messagehandler).blockLast(); /* .filter(g -> g.getGuild().blockOptional().isEmpty()) */.flatMap(messagehandler).blockLast();
} }
} }
private int invocationsBeforeThisSession = 0; private int invocationsBeforeThisSession = 0;
private void setup() { private void setup() {
Configuration.findConfigurationFilePath();
Configuration.findAndReadConfigurationFile(); Configuration.findAndReadConfigurationFile();
botToken = Configuration.getConfigurationParameter(TOKEN_KEY); botToken = Configuration.getConfigurationParameter(TOKEN_KEY);
@ -418,7 +429,10 @@ public class Priestess {
int invocationsTotal = invocationsBeforeThisSession + invocationsThisSession; int invocationsTotal = invocationsBeforeThisSession + invocationsThisSession;
log.log(Level.INFO, "Bean Goose has been invoked " + invocationsTotal + " times so far."); log.log(Level.INFO, "Bean Goose has been invoked " + invocationsTotal + " times so far.");
try {
Configuration.setConfigurationParameter(INVOCATIONS_KEY, Integer.toString(invocationsTotal)); Configuration.setConfigurationParameter(INVOCATIONS_KEY, Integer.toString(invocationsTotal));
} catch (FileNotFoundException e) {
}
Configuration.commitConfigurationToFile(); Configuration.commitConfigurationToFile();
log.log(Level.INFO, "Configuration committed to file."); log.log(Level.INFO, "Configuration committed to file.");
} }
@ -535,18 +549,8 @@ public class Priestess {
*/ */
private MessageStore setupMessageStore() { private MessageStore setupMessageStore() {
String mesglist = Configuration.getConfigurationParameter(MESSAGES); String mesglist = Configuration.getConfigurationParameter(MESSAGES);
File f = Paths.get(mesglist).toFile(); File f = new File(mesglist);
try { return new MessageStore(f);
MessageStore ms1 = new MessageStore(f);
return ms1;
} catch (IOException e) {
if (!f.exists()) {
log.log(Level.WARNING, "Message store file does not exist.");
} else {
log.log(Level.SEVERE, e.getMessage());
}
}
return null;
} }
private void reloadMessageStore() { private void reloadMessageStore() {
@ -747,7 +751,11 @@ public class Priestess {
String[] paytokens = tokenize(pay2); String[] paytokens = tokenize(pay2);
if (paytokens.length == 2) { if (paytokens.length == 2) {
log.log(Level.INFO, "setting configuration parameter " + paytokens[0] + " to " + paytokens[1]); log.log(Level.INFO, "setting configuration parameter " + paytokens[0] + " to " + paytokens[1]);
try {
Configuration.setConfigurationParameter(paytokens[0], paytokens[1]); Configuration.setConfigurationParameter(paytokens[0], paytokens[1]);
} catch (FileNotFoundException e) {
o.replyWith("");
}
} else { } else {
log.log(Level.INFO, "Invalid argument count for set configuration parameter command"); log.log(Level.INFO, "Invalid argument count for set configuration parameter command");
} }