From c86845c3eb35af50e461ca6a8905f1cc013ec847 Mon Sep 17 00:00:00 2001 From: dzmipt Date: Sun, 14 Jan 2024 20:48:06 +0100 Subject: [PATCH] refactoring Config.java --- src/studio/kdb/Config.java | 407 +----------------- src/studio/kdb/config/AbstractConfig.java | 374 ++++++++++++++++ src/studio/utils/FilesBackup.java | 13 +- src/studio/utils/PropertiesConfig.java | 39 +- test-integration/studio/utils/MockConfig.java | 18 +- 5 files changed, 440 insertions(+), 411 deletions(-) create mode 100644 src/studio/kdb/config/AbstractConfig.java diff --git a/src/studio/kdb/Config.java b/src/studio/kdb/Config.java index 07d5d4a4..d6cb2dcb 100755 --- a/src/studio/kdb/Config.java +++ b/src/studio/kdb/Config.java @@ -5,10 +5,10 @@ import studio.core.AuthenticationManager; import studio.core.Credentials; import studio.core.DefaultAuthenticationMechanism; +import studio.kdb.config.AbstractConfig; import studio.kdb.config.ActionOnExit; import studio.kdb.config.KdbMessageLimitAction; import studio.ui.ServerList; -import studio.ui.Util; import studio.utils.*; import studio.utils.log4j.EnvConfig; @@ -26,14 +26,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class Config { +public class Config extends AbstractConfig { private static final Logger log = LogManager.getLogger(); - private enum ConfigType { STRING, INT, DOUBLE, BOOLEAN, FONT, BOUNDS, COLOR, ENUM, SIZE, FILE_CHOOSER} - - private static final Map defaultValues = new HashMap(); - private static final Map configTypes = new HashMap(); - //@TODO migrate all other keys under such approach public static final String SHOW_SERVER_COMBOBOX = configDefault("showServerComboBox", ConfigType.BOOLEAN, true); @@ -101,21 +96,9 @@ private enum ConfigType { STRING, INT, DOUBLE, BOOLEAN, FONT, BOUNDS, COLOR, ENU public static final String KDB_MESSAGE_SIZE_LIMIT_MB = configDefault("kdbMessageSizeLimitMB", ConfigType.INT, 10); public static final String KDB_MESSAGE_SIZE_LIMIT_ACTION = configDefault("kdbMessageSizeLimitAction", ConfigType.ENUM, KdbMessageLimitAction.ASK); - private enum FontStyle { - Plain(Font.PLAIN), Bold(Font.BOLD), Italic(Font.ITALIC), ItalicAndBold(Font.BOLD|Font.ITALIC); - private int style; - - FontStyle(int style) { - this.style = style; - } - public int getStyle() { - return style; - } - } private static final String CONFIG_FILENAME = "studio.properties"; private static final String WORKSPACE_FILENAME = "workspace.properties"; - private static final String BACKUP_FOLDER = "backup"; private static final String VERSION13 = "1.3"; private static final String VERSION12 = "1.2"; @@ -124,8 +107,6 @@ public int getStyle() { private static final String VERSION = VERSION13; - private final String filename; - private PropertiesConfig config; private PropertiesConfig workspaceConfig; private Map servers; @@ -139,15 +120,14 @@ public int getStyle() { private TableConnExtractor tableConnExtractor; - private FilesBackup filesBackup; // Can be overridden in test cases protected static Config instance = new Config(); public enum ExecAllOption {Execute, Ask, Ignore} protected Config(String filename) { - this.filename = filename; - init(filename); + super(filename); + init(); } private static void copyConfig(String configFileName) throws IOException { @@ -159,8 +139,8 @@ private static void copyConfig(String configFileName) throws IOException { } } - private Config() { - filename = EnvConfig.getFilepath(CONFIG_FILENAME); + private static String getDefaulConfigFilename() { + String filename = EnvConfig.getFilepath(CONFIG_FILENAME); String env = EnvConfig.getEnvironment(); if (env != null && ! Files.exists(Paths.get(filename))) { @@ -172,7 +152,12 @@ private Config() { log.error("Error during copying configs", e); } } - init(filename); + return filename; + } + + private Config() { + super(getDefaulConfigFilename()); + init(); } void saveToDisk() { @@ -320,43 +305,13 @@ public static Config getInstance() { return instance; } - private void init(String filename) { - filesBackup = new FilesBackup(EnvConfig.getFilepath(BACKUP_FOLDER)); - config = new PropertiesConfig(filesBackup, filename); - workspaceConfig = new PropertiesConfig(filesBackup, getWorkspaceFilename()); - load(filename); + private void init() { + workspaceConfig = new PropertiesConfig(getWorkspaceFilename()); + checkForUpgrade(); initTableConnExtractor(); } - protected void load(String filename) { - Path file = Paths.get(filename); - Path dir = file.getParent(); - if (Files.notExists(dir)) { - try { - log.info("No folder with configuration found. Creating " + dir); - Files.createDirectories(dir); - } catch (IOException e) { - log.error("Can't create configuration folder {}", dir, e); - } - } - - if (Files.exists(file)) { - try { - InputStream in = Files.newInputStream(file); - config.load(in); - log.info("Loaded {} properties from config {}", config.size(), file); - in.close(); - } catch (IOException e) { - log.error("Can't read configuration from file {}", filename, e); - } - } - } - - public String getFilename() { - return filename; - } - private void upgradeTo12() { try { log.info("Found old config. Converting..."); @@ -439,10 +394,6 @@ private void checkForUpgrade() { config.setProperty("version", VERSION); } - protected void save() { - config.save(); - } - // "".split(",") return {""}; we need to get zero length array private String[] split(String str) { str = str.trim(); @@ -485,11 +436,6 @@ public void addServerToHistory(Server server) { save(); } - public void setAcceptedLicense(Date d) { - config.put("licenseAccepted", d.toString()); - save(); - } - public String[] getMRUFiles() { String mru = config.getProperty("mrufiles", ""); return split(mru); @@ -795,327 +741,4 @@ public void setServerTree(ServerTreeNode serverTree) { } } - private Object checkAndGetDefaultValue(String key, ConfigType passed) { - ConfigType type = configTypes.get(key); - if (type == null) { - throw new IllegalStateException("Ups... Wrong access to config " + key + ". The key wasn't defined"); - } - if (type != passed) { - throw new IllegalStateException("Ups... Wrong access to config " + key + ". Expected type: " + type + "; passed: " + passed); - } - return defaultValues.get(key); - } - - private static String configDefault(String key, ConfigType type, Object defaultValue) { - defaultValues.put(key, defaultValue); - configTypes.put(key, type); - - //Looks like a hack? How to make it more elegant? - if (type == ConfigType.FILE_CHOOSER) { - FileChooserConfig config = (FileChooserConfig) defaultValue; - configDefault(key + ".filename", ConfigType.STRING, config.getFilename()); - configDefault(key + ".prefSize", ConfigType.SIZE, config.getPreferredSize()); - } - - return key; - } - - private String get(String key, String defaultValue) { - String value = config.getProperty(key); - return value == null ? defaultValue : value; - } - - public String getString(String key) { - return get(key, (String) checkAndGetDefaultValue(key, ConfigType.STRING)); - } - - // Returns whether the value was changed - public boolean setString(String key, String value) { - String currentValue = getString(key); - if (currentValue.equals(value)) return false; - - config.setProperty(key, value); - save(); - return true; - } - - private boolean get(String key, boolean defaultValue) { - String value = config.getProperty(key); - if (value == null) return defaultValue; - - return Boolean.parseBoolean(value); - } - - public boolean getBoolean(String key) { - return get(key, (Boolean) checkAndGetDefaultValue(key, ConfigType.BOOLEAN)); - } - - // Returns whether the value was changed - public boolean setBoolean(String key, boolean value) { - boolean currentValue = getBoolean(key); - if (currentValue == value) { - return false; - } - - config.setProperty(key, "" + value); - save(); - return true; - } - - private double get(String key, double defaultValue) { - String value = config.getProperty(key); - if (value == null) return defaultValue; - - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - log.error("Failed to parse config key " + key + " from config", e); - } - return defaultValue; - } - - public double getDouble(String key) { - return get(key, (Double) checkAndGetDefaultValue(key, ConfigType.DOUBLE)); - } - - // Returns whether the value was changed - public boolean setDouble(String key, double value) { - double currentValue = getDouble(key); - if (currentValue == value) { - return false; - } - - config.setProperty(key, "" + value); - save(); - return true; - } - - private int get(String key, int defaultValue) { - String value = config.getProperty(key); - if (value == null) return defaultValue; - - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - log.error("Failed to parse config key " + key + " from config", e); - } - return defaultValue; - } - - public int getInt(String key) { - return get(key, (Integer) checkAndGetDefaultValue(key, ConfigType.INT)); - } - - // Returns whether the value was changed - public boolean setInt(String key, int value) { - int currentValue = getInt(key); - if (currentValue == value) { - return false; - } - - config.setProperty(key, "" + value); - save(); - return true; - } - - private Rectangle getBounds(String key, Object defaultBoundOrScale) { - try { - String strX = config.getProperty(key + ".x"); - String strY = config.getProperty(key + ".y"); - String strWidth = config.getProperty(key + ".width"); - String strHeight = config.getProperty(key + ".height"); - - if (strX != null && strY != null && strWidth != null && strHeight != null) { - Rectangle bounds = new Rectangle(Integer.parseInt(strX), Integer.parseInt(strY), - Integer.parseInt(strWidth), Integer.parseInt(strHeight)); - - if (Util.fitToScreen(bounds)) return bounds; - - log.info("Bounds of {} doesn't fit to any of current monitors - falling back to a default value", key); - } - - } catch (NumberFormatException e) { - log.error("Failed to parse bounds from config key " + key, e); - } - - DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getDefaultScreenDevice().getDisplayMode(); - - int width = displayMode.getWidth(); - int height = displayMode.getHeight(); - - int w,h; - - if (defaultBoundOrScale instanceof Dimension) { - Dimension defaultSize = (Dimension)defaultBoundOrScale; - w = Math.min(width / 2, defaultSize.width); - h = Math.min(height / 2, defaultSize.height); - } else { - double scale = 0.5; - if (defaultBoundOrScale instanceof Double) { - scale = (Double) defaultBoundOrScale; - } else { - log.error("Internal error. Wrong default value passed to getBounds - key = {}; value = {}", key, defaultBoundOrScale); - } - w = (int) (width * scale); - h = (int) (height * scale); - } - - int x = (width - w) / 2; - int y = (height - h) / 2; - return new Rectangle(x,y,w,h); - - } - - public Rectangle getBounds(String key) { - return getBounds(key, checkAndGetDefaultValue(key, ConfigType.BOUNDS)); - } - - public void setBounds(String key, Rectangle bound) { - config.setProperty(key + ".x", "" + bound.x); - config.setProperty(key + ".y", "" + bound.y); - config.setProperty(key + ".width", "" + bound.width); - config.setProperty(key + ".height", "" + bound.height); - save(); - } - - private Dimension get(String key, Dimension defaultValue) { - try { - String strWidth = config.getProperty(key + ".width"); - String strHeight = config.getProperty(key + ".height"); - - if (strWidth != null && strHeight != null) { - return new Dimension(Integer.parseInt(strWidth), Integer.parseInt(strHeight)); - } - - } catch (NumberFormatException e) { - log.error("Failed to parse dimension from config key " + key, e); - } - return defaultValue; - } - - public Dimension getSize(String key) { - return get(key, (Dimension) checkAndGetDefaultValue(key, ConfigType.SIZE)); - } - public boolean setSize(String key, Dimension value) { - Dimension currentValue = getSize(key); - if (currentValue.equals(value)) return false; - - config.setProperty(key + ".width", "" + value.width); - config.setProperty(key + ".height", "" + value.height); - save(); - return true; - } - - private FileChooserConfig get(String key, FileChooserConfig defaultValue) { - String filename = get(key + ".filename", (String) null); - Dimension size = get(key + ".prefSize", (Dimension) null); - - if (size != null && filename != null) { - return new FileChooserConfig(filename, size); - } - - return defaultValue; - } - - public FileChooserConfig getFileChooserConfig(String key) { - return get(key, (FileChooserConfig) checkAndGetDefaultValue(key, ConfigType.FILE_CHOOSER)); - } - - public boolean setFileChooserConfig(String key, FileChooserConfig value) { - FileChooserConfig currentValue = getFileChooserConfig(key); - if (currentValue.equals(value)) return false; - - setString(key + ".filename", value.getFilename()); - setSize(key + ".prefSize", value.getPreferredSize()); - save(); - return true; - } - - private Color get(String key, Color defaultValue) { - String value = config.getProperty(key); - if (value == null) return defaultValue; - - try { - return new Color(Integer.parseInt(value, 16)); - } catch (NumberFormatException e) { - log.error("Failed to parse {} for config key {}", value, key, e); - } - return defaultValue; - } - - public Color getColor(String key) { - return get(key, (Color) checkAndGetDefaultValue(key, ConfigType.COLOR)); - } - - // Returns whether the value was changed - public boolean setColor(String key, Color value) { - Color currentValue = getColor(key); - if (currentValue.equals(value)) { - return false; - } - config.setProperty(key, Integer.toHexString(value.getRGB()).substring(2)); - save(); - return true; - } - - private > T get(String key, T defaultValue) { - String value = config.getProperty(key); - if (value == null) return defaultValue; - - try { - return (T) Enum.valueOf(defaultValue.getClass(), value); - } catch (IllegalArgumentException e) { - log.error("Failed to parse {} for config key {}", value, key, e); - } - return defaultValue; - } - - public > T getEnum(String key) { - return get(key, (T) checkAndGetDefaultValue(key, ConfigType.ENUM)); - } - - public > boolean setEnum(String key, T value) { - T currentValue = getEnum(key); - if (currentValue == value) { - return false; - } - - config.setProperty(key, value.name()); - save(); - return true; - } - - private Font get(String key, Font defaultValue) { - String name = config.getProperty(key + ".name"); - if (name == null) return defaultValue; - - int size = get(key + ".size", 14); - int style = get(key +".style", FontStyle.Plain).getStyle(); - - return new Font(name, style, size); - } - - public Font getFont(String key) { - return get(key, (Font) checkAndGetDefaultValue(key, ConfigType.FONT)); - } - - // Returns whether the value was changed - public boolean setFont(String key, Font value) { - Font currentValue = getFont(key); - if (currentValue.equals(value)) - if (currentValue == value) { - return false; - } - config.setProperty(key + ".name", value.getName()); - config.setProperty(key + ".size", "" + value.getSize()); - - int style = value.getStyle(); - if (style < 0 || style > 3) style = 0; // Not sure if it is posible - FontStyle fontStyle = FontStyle.values()[style]; - config.setProperty(key + ".style", fontStyle.name()); - - save(); - return true; - } } diff --git a/src/studio/kdb/config/AbstractConfig.java b/src/studio/kdb/config/AbstractConfig.java new file mode 100644 index 00000000..b5809220 --- /dev/null +++ b/src/studio/kdb/config/AbstractConfig.java @@ -0,0 +1,374 @@ +package studio.kdb.config; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import studio.kdb.FileChooserConfig; +import studio.ui.Util; +import studio.utils.PropertiesConfig; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class AbstractConfig { + + private static final Logger log = LogManager.getLogger(); + + protected enum ConfigType { STRING, INT, DOUBLE, BOOLEAN, FONT, BOUNDS, COLOR, ENUM, SIZE, FILE_CHOOSER} + + protected enum FontStyle { + Plain(Font.PLAIN), Bold(Font.BOLD), Italic(Font.ITALIC), ItalicAndBold(Font.BOLD|Font.ITALIC); + private int style; + + FontStyle(int style) { + this.style = style; + } + public int getStyle() { + return style; + } + } + + private static final Map defaultValues = new HashMap(); + private static final Map configTypes = new HashMap(); + + protected PropertiesConfig config; + private final String filename; + + protected AbstractConfig(String filename) { + this.filename = filename; + config = new PropertiesConfig(filename); + } + + public String getFilename() { + return filename; + } + + protected void save() { + config.save(); + } + + private Object checkAndGetDefaultValue(String key, ConfigType passed) { + ConfigType type = configTypes.get(key); + if (type == null) { + throw new IllegalStateException("Oops... Wrong access to config " + key + ". The key wasn't defined"); + } + if (type != passed) { + throw new IllegalStateException("Oops... Wrong access to config " + key + ". Expected type: " + type + "; passed: " + passed); + } + return defaultValues.get(key); + } + + protected static String configDefault(String key, ConfigType type, Object defaultValue) { + defaultValues.put(key, defaultValue); + configTypes.put(key, type); + + //Looks like a hack? How to make it more elegant? + if (type == ConfigType.FILE_CHOOSER) { + FileChooserConfig config = (FileChooserConfig) defaultValue; + configDefault(key + ".filename", ConfigType.STRING, config.getFilename()); + configDefault(key + ".prefSize", ConfigType.SIZE, config.getPreferredSize()); + } + + return key; + } + + protected String get(String key, String defaultValue) { + String value = config.getProperty(key); + return value == null ? defaultValue : value; + } + + public String getString(String key) { + return get(key, (String) checkAndGetDefaultValue(key, ConfigType.STRING)); + } + + // Returns whether the value was changed + public boolean setString(String key, String value) { + String currentValue = getString(key); + if (currentValue.equals(value)) return false; + + config.setProperty(key, value); + save(); + return true; + } + + protected boolean get(String key, boolean defaultValue) { + String value = config.getProperty(key); + if (value == null) return defaultValue; + + return Boolean.parseBoolean(value); + } + + public boolean getBoolean(String key) { + return get(key, (Boolean) checkAndGetDefaultValue(key, ConfigType.BOOLEAN)); + } + + // Returns whether the value was changed + public boolean setBoolean(String key, boolean value) { + boolean currentValue = getBoolean(key); + if (currentValue == value) { + return false; + } + + config.setProperty(key, "" + value); + save(); + return true; + } + + protected double get(String key, double defaultValue) { + String value = config.getProperty(key); + if (value == null) return defaultValue; + + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + log.error("Failed to parse config key " + key + " from config", e); + } + return defaultValue; + } + + public double getDouble(String key) { + return get(key, (Double) checkAndGetDefaultValue(key, ConfigType.DOUBLE)); + } + + // Returns whether the value was changed + public boolean setDouble(String key, double value) { + double currentValue = getDouble(key); + if (currentValue == value) { + return false; + } + + config.setProperty(key, "" + value); + save(); + return true; + } + + protected int get(String key, int defaultValue) { + String value = config.getProperty(key); + if (value == null) return defaultValue; + + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + log.error("Failed to parse config key " + key + " from config", e); + } + return defaultValue; + } + + public int getInt(String key) { + return get(key, (Integer) checkAndGetDefaultValue(key, ConfigType.INT)); + } + + // Returns whether the value was changed + public boolean setInt(String key, int value) { + int currentValue = getInt(key); + if (currentValue == value) { + return false; + } + + config.setProperty(key, "" + value); + save(); + return true; + } + + private Rectangle getBounds(String key, Object defaultBoundOrScale) { + try { + String strX = config.getProperty(key + ".x"); + String strY = config.getProperty(key + ".y"); + String strWidth = config.getProperty(key + ".width"); + String strHeight = config.getProperty(key + ".height"); + + if (strX != null && strY != null && strWidth != null && strHeight != null) { + Rectangle bounds = new Rectangle(Integer.parseInt(strX), Integer.parseInt(strY), + Integer.parseInt(strWidth), Integer.parseInt(strHeight)); + + if (Util.fitToScreen(bounds)) return bounds; + + log.info("Bounds of {} doesn't fit to any of current monitors - falling back to a default value", key); + } + + } catch (NumberFormatException e) { + log.error("Failed to parse bounds from config key " + key, e); + } + + DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDisplayMode(); + + int width = displayMode.getWidth(); + int height = displayMode.getHeight(); + + int w,h; + + if (defaultBoundOrScale instanceof Dimension) { + Dimension defaultSize = (Dimension)defaultBoundOrScale; + w = Math.min(width / 2, defaultSize.width); + h = Math.min(height / 2, defaultSize.height); + } else { + double scale = 0.5; + if (defaultBoundOrScale instanceof Double) { + scale = (Double) defaultBoundOrScale; + } else { + log.error("Internal error. Wrong default value passed to getBounds - key = {}; value = {}", key, defaultBoundOrScale); + } + w = (int) (width * scale); + h = (int) (height * scale); + } + + int x = (width - w) / 2; + int y = (height - h) / 2; + return new Rectangle(x,y,w,h); + + } + + public Rectangle getBounds(String key) { + return getBounds(key, checkAndGetDefaultValue(key, ConfigType.BOUNDS)); + } + + public void setBounds(String key, Rectangle bound) { + config.setProperty(key + ".x", "" + bound.x); + config.setProperty(key + ".y", "" + bound.y); + config.setProperty(key + ".width", "" + bound.width); + config.setProperty(key + ".height", "" + bound.height); + save(); + } + + protected Dimension get(String key, Dimension defaultValue) { + try { + String strWidth = config.getProperty(key + ".width"); + String strHeight = config.getProperty(key + ".height"); + + if (strWidth != null && strHeight != null) { + return new Dimension(Integer.parseInt(strWidth), Integer.parseInt(strHeight)); + } + + } catch (NumberFormatException e) { + log.error("Failed to parse dimension from config key " + key, e); + } + return defaultValue; + } + + public Dimension getSize(String key) { + return get(key, (Dimension) checkAndGetDefaultValue(key, ConfigType.SIZE)); + } + public boolean setSize(String key, Dimension value) { + Dimension currentValue = getSize(key); + if (currentValue.equals(value)) return false; + + config.setProperty(key + ".width", "" + value.width); + config.setProperty(key + ".height", "" + value.height); + save(); + return true; + } + + protected FileChooserConfig get(String key, FileChooserConfig defaultValue) { + String filename = get(key + ".filename", (String) null); + Dimension size = get(key + ".prefSize", (Dimension) null); + + if (size != null && filename != null) { + return new FileChooserConfig(filename, size); + } + + return defaultValue; + } + + public FileChooserConfig getFileChooserConfig(String key) { + return get(key, (FileChooserConfig) checkAndGetDefaultValue(key, ConfigType.FILE_CHOOSER)); + } + + public boolean setFileChooserConfig(String key, FileChooserConfig value) { + FileChooserConfig currentValue = getFileChooserConfig(key); + if (currentValue.equals(value)) return false; + + setString(key + ".filename", value.getFilename()); + setSize(key + ".prefSize", value.getPreferredSize()); + save(); + return true; + } + + protected Color get(String key, Color defaultValue) { + String value = config.getProperty(key); + if (value == null) return defaultValue; + + try { + return new Color(Integer.parseInt(value, 16)); + } catch (NumberFormatException e) { + log.error("Failed to parse {} for config key {}", value, key, e); + } + return defaultValue; + } + + public Color getColor(String key) { + return get(key, (Color) checkAndGetDefaultValue(key, ConfigType.COLOR)); + } + + // Returns whether the value was changed + public boolean setColor(String key, Color value) { + Color currentValue = getColor(key); + if (currentValue.equals(value)) { + return false; + } + config.setProperty(key, Integer.toHexString(value.getRGB()).substring(2)); + save(); + return true; + } + + protected > T get(String key, T defaultValue) { + String value = config.getProperty(key); + if (value == null) return defaultValue; + + try { + return (T) Enum.valueOf(defaultValue.getClass(), value); + } catch (IllegalArgumentException e) { + log.error("Failed to parse {} for config key {}", value, key, e); + } + return defaultValue; + } + + public > T getEnum(String key) { + return get(key, (T) checkAndGetDefaultValue(key, ConfigType.ENUM)); + } + + public > boolean setEnum(String key, T value) { + T currentValue = getEnum(key); + if (currentValue == value) { + return false; + } + + config.setProperty(key, value.name()); + save(); + return true; + } + + protected Font get(String key, Font defaultValue) { + String name = config.getProperty(key + ".name"); + if (name == null) return defaultValue; + + int size = get(key + ".size", 14); + int style = get(key +".style", FontStyle.Plain).getStyle(); + + return new Font(name, style, size); + } + + public Font getFont(String key) { + return get(key, (Font) checkAndGetDefaultValue(key, ConfigType.FONT)); + } + + // Returns whether the value was changed + public boolean setFont(String key, Font value) { + Font currentValue = getFont(key); + if (currentValue.equals(value)) + if (currentValue == value) { + return false; + } + config.setProperty(key + ".name", value.getName()); + config.setProperty(key + ".size", "" + value.getSize()); + + int style = value.getStyle(); + if (style < 0 || style > 3) style = 0; // Not sure if it is posible + FontStyle fontStyle = FontStyle.values()[style]; + config.setProperty(key + ".style", fontStyle.name()); + + save(); + return true; + } + +} diff --git a/src/studio/utils/FilesBackup.java b/src/studio/utils/FilesBackup.java index a8bae4ca..6d1529a3 100644 --- a/src/studio/utils/FilesBackup.java +++ b/src/studio/utils/FilesBackup.java @@ -3,6 +3,7 @@ import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import studio.utils.log4j.EnvConfig; import java.io.FileOutputStream; import java.io.IOException; @@ -20,6 +21,8 @@ public class FilesBackup { + private static final String BACKUP_FOLDER = "backup"; + protected static long BACKUP_PERIOD_MILLIS = 24*60*60*1000L; // ond day private final static int RETAIN_BACKUP_HISTORY_DAYS = 14; // keep the last 2 weeks @@ -31,12 +34,18 @@ public class FilesBackup { //Useful in tests private static boolean enabled = true; + private static final FilesBackup instance = new FilesBackup(EnvConfig.getFilepath(BACKUP_FOLDER)); + + public static FilesBackup getInstance() { + return instance; + } + public static void setEnabled(boolean enabled) { log.info("setEnabled {}", enabled); FilesBackup.enabled = enabled; } - public FilesBackup(String backupFolder) { + protected FilesBackup(String backupFolder) { backupDirPath = Paths.get(backupFolder); if (!enabled) return; @@ -90,7 +99,7 @@ public void close() throws IOException { }; } - public void backup(String filename) throws IOException { + protected void backup(String filename) throws IOException { if (!enabled) return; if (Files.notExists(Paths.get(filename))) return; diff --git a/src/studio/utils/PropertiesConfig.java b/src/studio/utils/PropertiesConfig.java index aa962ca8..cd941386 100644 --- a/src/studio/utils/PropertiesConfig.java +++ b/src/studio/utils/PropertiesConfig.java @@ -6,6 +6,9 @@ import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -25,24 +28,46 @@ public class PropertiesConfig extends Properties { private final static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); private final String filename; - private final FilesBackup filesBackup; private Properties propertiesToSave = null; - - public PropertiesConfig(FilesBackup filesBackup, String filename) { - this.filesBackup = filesBackup; + public PropertiesConfig(String filename) { this.filename = filename; + load(); } public PropertiesConfig cloneConfig() { saveToDisk(); - PropertiesConfig config = new PropertiesConfig(filesBackup, filename); + PropertiesConfig config = new PropertiesConfig(filename); config.putAll(this); return config; } + protected void load() { + Path file = Paths.get(filename); + Path dir = file.getParent(); + if (Files.notExists(dir)) { + try { + log.info("No folder with configuration found. Creating " + dir); + Files.createDirectories(dir); + } catch (IOException e) { + log.error("Can't create configuration folder {}", dir, e); + } + } + + if (Files.exists(file)) { + try { + InputStream in = Files.newInputStream(file); + load(in); + log.info("Loaded {} properties from config {}", size(), file); + in.close(); + } catch (IOException e) { + log.error("Can't read configuration from file {}", filename, e); + } + } + } + public synchronized void save() { if (propertiesToSave == null) { executor.schedule(this::saveToDisk, SAVE_DELAY_SEC, TimeUnit.SECONDS); @@ -59,7 +84,7 @@ private synchronized ByteArrayOutputStream getStreamToSave() { super.store(buffer, "Auto-generated by Studio for kdb+"); return buffer; } catch (IOException e) { - log.error("Error in serializing config for the file {}", filename, e); + log.error("Oops, unexpected error", e); } finally { propertiesToSave = null; } @@ -71,7 +96,7 @@ public void saveToDisk() { ByteArrayOutputStream buffer = getStreamToSave(); if (buffer == null) return; - try (OutputStream out = filesBackup.newFileOutputStream(filename)) { + try (OutputStream out = FilesBackup.getInstance().newFileOutputStream(filename)) { byte[] lineSeparator = System.getProperty("line.separator").getBytes(CHARSET); BufferedReader reader = new BufferedReader( diff --git a/test-integration/studio/utils/MockConfig.java b/test-integration/studio/utils/MockConfig.java index 979c7d29..37b0f78f 100644 --- a/test-integration/studio/utils/MockConfig.java +++ b/test-integration/studio/utils/MockConfig.java @@ -9,16 +9,19 @@ import studio.kdb.Config; import studio.kdb.Workspace; +import java.io.File; +import java.io.IOException; + public class MockConfig extends Config { private static boolean initialized = false; - public static synchronized void init() { + public static synchronized void init() throws IOException { if (initialized) return; FilesBackup.setEnabled(false); - - Config.instance = new MockConfig(); + File configFileName = File.createTempFile("kdbStudio", ".properties"); + Config.instance = new MockConfig(configFileName.getAbsolutePath()); LoggerContext context = LoggerContext.getContext(false); for (Logger logger: context.getLoggers() ) { Appender[] appenders = logger.getAppenders().values().toArray(new Appender[0]); @@ -36,13 +39,8 @@ public static synchronized void init() { private Workspace workspace; - private MockConfig() { - super(""); - } - - @Override - protected void load(String filename) { - // nothing + private MockConfig(String filename) { + super(filename); } @Override