/******************************************************************************* * sdrtrunk * Copyright (C) 2014-2017 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * ******************************************************************************/ package properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.ThreadPool; import java.awt.*; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * SystemProperties - provides an isolated instance of properties for the application */ public class SystemProperties { private final static Logger mLog = LoggerFactory.getLogger(SystemProperties.class); private static String DEFAULT_APP_ROOT = "SDRTrunk"; private static String PROPERTIES_FILENAME = "SDRTrunk.properties"; private static SystemProperties INSTANCE; private static Properties mProperties; private Path mPropertiesPath; private String mApplicationName; private AtomicBoolean mSavePending = new AtomicBoolean(); private SystemProperties() { mProperties = new Properties(); } /** * Returns a SINGLETON instance of the application properties set * * @return */ public static SystemProperties getInstance() { if(INSTANCE == null) { INSTANCE = new SystemProperties(); } return INSTANCE; } /** * Saves any currently changed settings to the application properties file */ private void save() { if(mSavePending.compareAndSet(false, true)) { ThreadPool.SCHEDULED.schedule(new SavePropertiesTask(), 2, TimeUnit.SECONDS); } } /** * Application root directory. Normally returns "SDRTRunk" from the user's * home directory, unless that has been changed to another location on the * file system by the user. */ public Path getApplicationRootPath() { Path retVal = null; String root = get("root.directory", DEFAULT_APP_ROOT); if(root.equalsIgnoreCase(DEFAULT_APP_ROOT)) { retVal = Paths.get( System.getProperty("user.home"), DEFAULT_APP_ROOT); } else { retVal = Paths.get(root); } return retVal; } public Path getApplicationFolder(String folder) { Path retVal = getApplicationRootPath().resolve(folder); if(!Files.exists(retVal)) { try { Files.createDirectory(retVal); } catch(IOException e) { mLog.error("SystemProperties - exception while creating app folder [" + folder + "]", e); } } return retVal; } public void logCurrentSettings() { if(mPropertiesPath == null) { mLog.info("SystemProperties - no properties file loaded - using defaults"); } else { mLog.info("SystemProperties - application properties loaded [" + mPropertiesPath.toString() + "]"); } } /** * Loads the properties file into this properties set */ public void load(Path propertiesPath) { if(propertiesPath != null) { mPropertiesPath = propertiesPath; if(Files.exists(mPropertiesPath)) { try(InputStream in = new FileInputStream(propertiesPath.toString())) { mProperties.load(in); } catch(IOException ioe) { mLog.error("Error loading system properties file", ioe.getMessage()); } } } mLog.info("SystemProperties - loaded [" + propertiesPath.toString() + "]"); } public String getApplicationName() { if(mApplicationName == null) { StringBuilder sb = new StringBuilder(); sb.append("sdrtrunk"); try(BufferedReader reader = new BufferedReader( new InputStreamReader(this.getClass() .getResourceAsStream("/sdrtrunk-version")))) { String version = reader.readLine(); if(version != null) { sb.append(" V"); sb.append(version); } } catch(Exception e) { mLog.error("Couldn't read sdrtrunk version from application jar file"); } mApplicationName = sb.toString(); } return mApplicationName; } /** * Returns the value of the property, or null if the property doesn't exist */ private String get(String key) { return mProperties.getProperty(key); } /** * Returns the value of the property, or the defaultValue if the * property doesn't exist */ public String get(String key, String defaultValue) { String value = get(key); if(value != null) { return value; } set(key, defaultValue); return defaultValue; } /** * Returns the value of the property, or the defaultValue if the * property doesn't exist */ public boolean get(String key, boolean defaultValue) { String value = get(key); if(value != null) { try { boolean stored = Boolean.parseBoolean(value); return stored; } catch(Exception e) { //Do nothing, we couldn't parse the stored value } } set(key, String.valueOf(defaultValue)); return defaultValue; } /** * Returns the value of the property, or the defaultValue if the * property doesn't exist */ public int get(String key, int defaultValue) { String value = get(key); if(value != null) { try { int stored = Integer.parseInt(value); return stored; } catch(Exception e) { //Do nothing, we couldn't parse the stored value } } set(key, String.valueOf(defaultValue)); return defaultValue; } /** * Sets (overrides) the property key with the new value */ public void set(String key, String value) { mProperties.setProperty(key, value); save(); } /** * Sets (overrides) the property key with the new boolean value */ public void set(String key, boolean value) { set(key, String.valueOf(value)); } /** * Sets (overrides) the property key with the new integer value */ public void set(String key, int value) { set(key, String.valueOf(value)); } /** * Gets the named color property, storing the default value in properties file if it doesn't exist. * * @param key identifying the color property * @param defaultColor to use for creating the property if it doesn't exist * @return named color */ public Color get(String key, Color defaultColor) { return new Color(get(key, defaultColor.getRGB()), true); } /** * Creates a new color instance with the RGB values from color argument and translucency (alpha) argument * @param color containing RGB values * @param alpha desired translucency/alpha value * @return new color with adjusted alpha value */ public static Color getTranslucent(Color color, int alpha) { return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); } public class SavePropertiesTask implements Runnable { @Override public void run() { if(mSavePending.compareAndSet(true, false)) { Path propsPath = getApplicationRootPath().resolve(PROPERTIES_FILENAME); try(OutputStream out = new FileOutputStream(propsPath.toString())) { String comments = "SDRTrunk - SDR Trunking Decoder Application Settings"; mProperties.store(out, comments); } catch(IOException ioe) { mLog.error("Error saving system properties file [" + propsPath.toString() + "]", ioe); } } } } }