/* Copyright (C) 2011 Peter Hanecak <hanecak@opendata.sk> * * This file is part of Open Data Node. * * Open Data Node 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. * * Open Data Node 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 Open Data Node. If not, see <http://www.gnu.org/licenses/>. */ package sk.opendatanode.utils; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Hashtable; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO: This is a copy of file from 'open-data-node'. Create * 'open-data-node-common' module so that we not need to duplicate files. */ public class ApplicationProperties extends Properties { private static final long serialVersionUID = 4684911806029642651L; public final String ODN_PROPERTY_SUBDIR = ".odn"; private static Logger logger = LoggerFactory.getLogger(ApplicationProperties.class); private static Hashtable<String, ApplicationProperties> instances = new Hashtable<String, ApplicationProperties>(); private ApplicationProperties(String propertiesFileName) throws IOException { super(); // load the default properties from the bundle this.load(getClass().getResourceAsStream(propertiesFileName)); logger.info("loaded default properties from '" + propertiesFileName + "' from the bundle"); // load the properties from the user home directory and - if found and // properly loaded - use them to override properties from the bundle File homeSubdirFn = new File(System.getProperty("user.home"), ODN_PROPERTY_SUBDIR); File overrideFn = new File(homeSubdirFn, propertiesFileName); if (overrideFn.exists() && overrideFn.isFile() && overrideFn.canRead()) { FileInputStream in = new FileInputStream(overrideFn); Properties overrides = new Properties(); overrides.load(in); this.putAll(overrides); logger.info("user properties loaded from '" + overrideFn.getAbsolutePath() + "'"); } } /** * Load properties from given file name. Properties are loaded only once from one unique file name. * * Properties load procedure: * * <ol> * <li>{@code propertiesFileName} is loaded from resources bundled with * application</li> * <li>if file {@code propertiesFileName} exists in subdirectory * {@code .odn} in user's home directory (as specified by {@code user.home} * system property), properties are loaded from that file too and they are * then added to the properties loaded from the bundled resources</li> * <li>the resulting set of properties are then present in the instance of * this class</li> * </ol> * * This allows for: * * <ul> * <li>all the necessary properties be specified in bundled property file</li> * <li>user/administrator of the application can override some or all * properties in the file * {@code <user.home>/.odn/<propertiesFileName>} * </ul> * * TODO: As of now, we're using this as 'new * ApplicationProperties("/file.properties")' => clarify the usage if * staring '/'! * * @param propertiesFileName * properties file name * @throws IOException * when loading of the properties from bundle or file fails */ public static ApplicationProperties getInstance(String propertiesFileName) throws IOException { ApplicationProperties ap = instances.get(propertiesFileName); if (ap == null) { ap = new ApplicationProperties(propertiesFileName); instances.put(propertiesFileName, ap); } return ap; } }