/* * Copyright (c) JForum Team * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2) Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of "Rafael Steil" nor * the names of its contributors may be used to endorse * or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * This file creating date: Feb 24, 2003 / 8:25:35 PM * The JForum Project * http://www.jforum.net */ package net.jforum.util.preferences; import java.io.*; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Vector; import net.jforum.ConfigLoader; import net.jforum.exceptions.ForumException; import org.apache.log4j.Logger; /** * <p>Store global configurations used in the system. * This is an helper class used to access the values * defined at SystemGlobals.properties and related * config files.</p> * * <p> * Transient values are stored in a special place, and are not * modified when you change a regular key's value. * </p> * * @author Rafael Steil * @author Pieter Olivier * @version $Id: SystemGlobals.java,v 1.35 2007/09/02 15:51:04 andowson Exp $ */ public class SystemGlobals implements VariableStore { private static SystemGlobals globals = new SystemGlobals(); private String defaultConfig; private String installationConfig; private Properties defaults = new Properties(); private Properties installation = new Properties(); private Map objectProperties = new HashMap(); private static List additionalDefaultsList = new ArrayList(); private static Properties queries = new Properties(); private static Properties transientValues = new Properties(); private VariableExpander expander = new VariableExpander(this, "${", "}"); private static final Logger logger = Logger.getLogger(SystemGlobals.class); private SystemGlobals() {} /** * Initialize the global configuration * @param appPath The application path (normally the path to the webapp base dir * @param mainConfigurationFile The file containing system defaults (when null, defaults to <appPath>/WEB-INF/config/default.conf) */ public static void initGlobals(String appPath, String mainConfigurationFile) { globals = new SystemGlobals(); globals.buildSystem(appPath, mainConfigurationFile); //pinke@trydone.com try { getlocalesFromFile(); } catch (IOException e) { logger.error(e); } } public static void reset() { globals.defaults.clear(); globals.installation.clear(); additionalDefaultsList.clear(); queries.clear(); transientValues.clear(); } private void buildSystem(String appPath, String mainConfigurationFile) { if (mainConfigurationFile == null) { throw new InvalidParameterException("defaultConfig could not be null"); } this.defaultConfig = mainConfigurationFile; this.defaults = new Properties(); this.defaults.put(ConfigKeys.APPLICATION_PATH, appPath); this.defaults.put(ConfigKeys.DEFAULT_CONFIG, mainConfigurationFile); SystemGlobals.loadDefaults(); this.installation = new Properties(); this.installationConfig = getVariableValue(ConfigKeys.INSTALLATION_CONFIG); for (Iterator iter = additionalDefaultsList.iterator(); iter.hasNext(); ) { loadAdditionalDefaults((String)iter.next()); } if (new File(this.installationConfig).exists()) { loadAdditionalDefaults(this.installationConfig); } } /** * Sets a value for some property * * @param field The property name * @param value The property value * @see #getVariableValue(String) * */ public static void setValue(String field, String value) { globals.installation.put(field, value); globals.expander.clearCache(); } public static void setObjectValue(String field, Object value) { globals.objectProperties.put(field, value); } public static Object getObjectValue(String field) { return globals.objectProperties.get(field); } /** * Set a transient configuration value (a value that will not be saved) * @param field The name of the configuration option * @param value The value of the configuration option */ public static void setTransientValue(String field, String value) { transientValues.put(field, value); } /** * Load system defaults */ public static void loadDefaults() { try { FileInputStream input = new FileInputStream(globals.defaultConfig); globals.defaults.load(input); input.close(); globals.expander.clearCache(); } catch (IOException e) { throw new ForumException(e); } } /** * Merge additional configuration defaults * * @param file File from which to load the additional defaults */ public static void loadAdditionalDefaults(String file) { if (!new File(file).exists()) { logger.info("Cannot find file " + file + ". Will ignore it"); return; } try { FileInputStream input = new FileInputStream(file); globals.installation.load(input); input.close(); } catch (IOException e) { throw new ForumException(e); } if (!additionalDefaultsList.contains(file)) { additionalDefaultsList.add(file); } } /** * Save installation defaults */ public static void saveInstallation() { // We need this temporary "p" because, when // new FileOutputStream() is called, it will // raise an event to the TimerTask who is listen // for file modifications, which then reloads the // configurations from the filesystem, overwriting // our new keys. class SortedProperties extends Properties{ public synchronized Enumeration keys() { Enumeration keysEnum = super.keys(); Vector keyList = new Vector(); while(keysEnum.hasMoreElements()){ keyList.add(keysEnum.nextElement()); } Collections.sort(keyList); return keyList.elements(); } } Properties p = new SortedProperties(); p.putAll(globals.installation); try { FileOutputStream out = new FileOutputStream(globals.installationConfig); p.store(out, "Installation specific configuration options"); out.close(); } catch (IOException e) { throw new ForumException(e); } ConfigLoader.listenInstallationConfig(); } /** * Gets the value of some property * * @param field The property name to retrieve the value * @return String with the value, or <code>null</code> if not found * @see #setValue(String, String) * */ public static String getValue(String field) { return globals.getVariableValue(field); } public static String getTransientValue(String field) { return transientValues.getProperty(field); } /** * Retrieve an integer-valued configuration field * * @param field Name of the configuration option * @return The value of the configuration option * @exception NullPointerException when the field does not exists */ public static int getIntValue(String field) { return Integer.parseInt(getValue(field)); } /** * Retrieve an boolean-values configuration field * * @param field name of the configuration option * @return The value of the configuration option * @exception NullPointerException when the field does not exists */ public static boolean getBoolValue(String field) { return "true".equals(getValue(field)); } /** * Return the value of a configuration value as a variable. Variable expansion is performe * on the result. * * @param field The field name to retrieve * @return The value of the field if present or null if not */ public String getVariableValue(String field) { String preExpansion = globals.installation.getProperty(field); if (preExpansion == null) { preExpansion = this.defaults.getProperty(field); if (preExpansion == null) { return null; } } return expander.expandVariables(preExpansion); } /** * Sets the application's root directory * * @param ap String containing the complete path to the root dir * @see #getApplicationPath * */ public static void setApplicationPath(String ap) { setValue(ConfigKeys.APPLICATION_PATH, ap); } /** * Getst the complete path to the application's root dir * * @return String with the path * @see #setApplicationPath * */ public static String getApplicationPath() { return getValue(ConfigKeys.APPLICATION_PATH); } /** * Gets the path to the resource's directory. * This method returns the directory name where the config * files are stored. * Caso queira saber o caminho absoluto do diretorio, voce precisa * usar * Note that this method does not return the complete path. If you * want the full path, you must use * <blockquote><pre>SystemGlobals.getApplicationPath() + SystemGlobals.getApplicationResourcedir()</pre></blockquote> * * @return String with the name of the resource dir, relative * to application's root dir. * @see #getApplicationPath() * */ public static String getApplicationResourceDir() { return getValue(ConfigKeys.RESOURCE_DIR); } /** * Load the SQL queries * * @param queryFile Complete path to the SQL queries file. **/ public static void loadQueries(String queryFile) { FileInputStream fis = null; try { fis = new FileInputStream(queryFile); queries.load(fis); } catch (IOException e) { throw new ForumException(e); } finally { if (fis != null) { try { fis.close(); } catch (Exception e) {} } } } /** * Gets some SQL statement. * * @param sql The query's name, as defined in the file loaded by * {@link #loadQueries(String)} * @return The SQL statement, or <code>null</code> if not found. * */ public static String getSql(String sql) { return queries.getProperty(sql); } /** * Retrieve an iterator that iterates over all known configuration keys * * @return An iterator that iterates over all known configuration keys */ public static Iterator fetchConfigKeyIterator() { return globals.defaults.keySet().iterator(); } public static Properties getConfigData() { return new Properties(globals.defaults); } private static Properties locales; /** * * <p> pinke@trydone.com <p> * @return locales Properties * @throws IOException */ public static Properties getLocales() throws IOException { if(locales==null){ return getlocalesFromFile(); } return locales; } public static List getLocaleList() throws IOException { Properties ls = getLocales(); List localesList = new ArrayList(); for (Enumeration e = ls.keys(); e.hasMoreElements();) { localesList.add(e.nextElement()); } return localesList; } /** * <p> pinke@trydone.com <p> * @return locales Properties * @throws IOException */ public static Properties getlocalesFromFile() throws IOException { locales = new Properties(); // FileInputStream fis = new FileInputStream(SystemGlobals.getValue(ConfigKeys.CONFIG_DIR) // + "/languages/locales.properties"); FileInputStream fis = new FileInputStream(SystemGlobals.getApplicationResourceDir() + "/" + SystemGlobals.getValue(ConfigKeys.LOCALES_DIR) +getValue(ConfigKeys.LOCALES_NAMES)); locales.load(fis); fis.close(); return locales; } }