/**
* $RCSfile$
* $Revision: 3505 $
* $Date: 2006-03-01 20:00:53 -0300 (Wed, 01 Mar 2006) $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.util;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.text.DateFormat;
/**
* Controls Jive properties. Jive properties are only meant to be set and retrieved
* by core Jive classes. Properties are stored in XML format.<p>
*
* When starting up the application this class needs to be configured so that the initial
* configuration of the application may be loaded from the configuration file. The configuration
* file holds properties stored in XML format. Use {@link #setHomeDirectory(String)} and
* {@link #setConfigName(String)} for setting the home directory and path to the configuration file.<p>
*
* XML property names must be in the form <code>prop.name</code> - parts of the name must
* be seperated by ".". The value can be any valid String, including strings with line breaks.<p>
*
* This class was copied from Openfire. Properties stored in the DB were removed from the code.
* Modified #getBooleanProperty to use properties stored in XML.
*/
public class JiveGlobals {
private static String JIVE_CONFIG_FILENAME = "conf" + File.separator + "manager.xml";
/**
* Location of the jiveHome directory. All configuration files should be
* located here.
*/
private static String home = null;
public static boolean failedLoading = false;
private static XMLProperties xmlProperties = null;
private static Locale locale = null;
private static TimeZone timeZone = null;
private static DateFormat dateTimeFormat = null;
/**
* Returns the global Locale used by Jive. A locale specifies language
* and country codes, and is used for internationalization. The default
* locale is system dependant - Locale.getDefault().
*
* @return the global locale used by Jive.
*/
public static Locale getLocale() {
if (locale == null) {
if (xmlProperties != null) {
String [] localeArray;
String localeProperty = xmlProperties.getProperty("locale");
if (localeProperty != null) {
localeArray = localeProperty.split("_");
}
else {
localeArray = new String[] {"", ""};
}
String language = localeArray[0];
if (language == null) {
language = "";
}
String country = "";
if (localeArray.length == 2) {
country = localeArray[1];
}
// If no locale info is specified, return the system default Locale.
if (language.equals("") && country.equals("")) {
locale = Locale.getDefault();
}
else {
locale = new Locale(language, country);
}
}
else {
return Locale.getDefault();
}
}
return locale;
}
/**
* Sets the global locale used by Jive. A locale specifies language
* and country codes, and is used for formatting dates and numbers.
* The default locale is Locale.US.
*
* @param newLocale the global Locale for Jive.
*/
public static void setLocale(Locale newLocale) {
locale = newLocale;
// Save values to Jive properties.
setXMLProperty("locale", locale.toString());
}
/**
* Returns the global TimeZone used by Jive. The default is the VM's
* default time zone.
*
* @return the global time zone used by Jive.
*/
public static TimeZone getTimeZone() {
if (timeZone == null) {
timeZone = TimeZone.getDefault();
}
return timeZone;
}
/**
* Formats a Date object to return a date and time using the global locale.
*
* @param date the Date to format.
* @return a String representing the date and time.
*/
public static String formatDateTime(Date date) {
if (dateTimeFormat == null) {
dateTimeFormat = DateFormat
.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, getLocale());
dateTimeFormat.setTimeZone(getTimeZone());
}
return dateTimeFormat.format(date);
}
/**
* Returns the location of the <code>home</code> directory.
*
* @return the location of the home dir.
*/
public static String getHomeDirectory() {
if (xmlProperties == null) {
loadSetupProperties();
}
return home;
}
/**
* Sets the location of the <code>home</code> directory. The directory must exist and the
* user running the application must have read and write permissions over the specified
* directory.
*
* @param pathname the location of the home dir.
*/
public static void setHomeDirectory(String pathname) {
File mh = new File(pathname);
// Do a permission check on the new home directory
if (!mh.exists()) {
Log.error("Error - the specified home directory does not exist (" + pathname + ")");
}
else if (!mh.canRead() || !mh.canWrite()) {
Log.error("Error - the user running this application can not read " +
"and write to the specified home directory (" + pathname + "). " +
"Please grant the executing user read and write permissions.");
}
else {
home = pathname;
}
}
/**
* Returns a local property. Local properties are stored in the file defined in
* <tt>JIVE_CONFIG_FILENAME</tt> that exists in the <tt>home</tt> directory.
* Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* <foo>
* <bar>
* <prop>some value</prop>
* </bar>
* </foo>
* </pre>
*
* @param name the name of the property to return.
* @return the property value specified by name.
*/
public static String getXMLProperty(String name) {
if (xmlProperties == null) {
loadSetupProperties();
}
// home not loaded?
if (xmlProperties == null) {
return null;
}
return xmlProperties.getProperty(name);
}
/**
* Returns a local property. Local properties are stored in the file defined in
* <tt>JIVE_CONFIG_FILENAME</tt> that exists in the <tt>home</tt> directory.
* Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* <foo>
* <bar>
* <prop>some value</prop>
* </bar>
* </foo>
* </pre>
*
* If the specified property can't be found, the <tt>defaultValue</tt> will be returned.
*
* @param name the name of the property to return.
* @param defaultValue the default value for the property.
* @return the property value specified by name.
*/
public static String getXMLProperty(String name, String defaultValue) {
if (xmlProperties == null) {
loadSetupProperties();
}
// home not loaded?
if (xmlProperties == null) {
return null;
}
String value = xmlProperties.getProperty(name);
if (value == null) {
value = defaultValue;
}
return value;
}
/**
* Returns an integer value local property. Local properties are stored in the file defined in
* <tt>JIVE_CONFIG_FILENAME</tt> that exists in the <tt>home</tt> directory.
* Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* <foo>
* <bar>
* <prop>some value</prop>
* </bar>
* </foo>
* </pre>
*
* If the specified property can't be found, or if the value is not a number, the
* <tt>defaultValue</tt> will be returned.
*
* @param name the name of the property to return.
* @param defaultValue value returned if the property could not be loaded or was not
* a number.
* @return the property value specified by name or <tt>defaultValue</tt>.
*/
public static int getXMLProperty(String name, int defaultValue) {
String value = getXMLProperty(name);
if (value != null) {
try {
return Integer.parseInt(value);
}
catch (NumberFormatException nfe) {
// Ignore.
}
}
return defaultValue;
}
/**
* Sets a local property. If the property doesn't already exists, a new
* one will be created. Local properties are stored in the file defined in
* <tt>JIVE_CONFIG_FILENAME</tt> that exists in the <tt>home</tt> directory.
* Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* <foo>
* <bar>
* <prop>some value</prop>
* </bar>
* </foo>
* </pre>
*
* @param name the name of the property being set.
* @param value the value of the property being set.
*/
public static void setXMLProperty(String name, String value) {
if (xmlProperties == null) {
loadSetupProperties();
}
// jiveHome not loaded?
if (xmlProperties != null) {
xmlProperties.setProperty(name, value);
}
}
/**
* Sets multiple local properties at once. If a property doesn't already exists, a new
* one will be created. Local properties are stored in the file defined in
* <tt>JIVE_CONFIG_FILENAME</tt> that exists in the <tt>home</tt> directory.
* Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* <foo>
* <bar>
* <prop>some value</prop>
* </bar>
* </foo>
* </pre>
*
* @param propertyMap a map of properties, keyed on property name.
*/
public static void setXMLProperties(Map<String, String> propertyMap) {
if (xmlProperties == null) {
loadSetupProperties();
}
if (xmlProperties != null) {
xmlProperties.setProperties(propertyMap);
}
}
/**
* Return all immediate children property values of a parent local property as a list of strings,
* or an empty list if there are no children. For example, given
* the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, <tt>X.Y.C</tt> and <tt>X.Y.C.D</tt>, then
* the immediate child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
* <tt>C</tt> (the value of <tt>C.D</tt> would not be returned using this method).<p>
*
* Local properties are stored in the file defined in <tt>JIVE_CONFIG_FILENAME</tt> that exists
* in the <tt>home</tt> directory. Properties are always specified as "foo.bar.prop",
* which would map to the following entry in the XML file:
* <pre>
* <foo>
* <bar>
* <prop>some value</prop>
* </bar>
* </foo>
* </pre>
*
*
* @param parent the name of the parent property to return the children for.
* @return all child property values for the given parent.
*/
public static List getXMLProperties(String parent) {
if (xmlProperties == null) {
loadSetupProperties();
}
// jiveHome not loaded?
if (xmlProperties == null) {
return Collections.EMPTY_LIST;
}
String[] propNames = xmlProperties.getChildrenProperties(parent);
List<String> values = new ArrayList<String>();
for (String propName : propNames) {
String value = getXMLProperty(parent + "." + propName);
if (value != null) {
values.add(value);
}
}
return values;
}
/**
* Returns an integer value Jive property. If the specified property doesn't exist, the
* <tt>defaultValue</tt> will be returned.
*
* @param name the name of the property to return.
* @param defaultValue value returned if the property doesn't exist or was not
* a number.
* @return the property value specified by name or <tt>defaultValue</tt>.
*/
public static int getIntProperty(String name, int defaultValue) {
String value = getXMLProperty(name);
if (value != null) {
try {
return Integer.parseInt(value);
}
catch (NumberFormatException nfe) {
// Ignore.
}
}
return defaultValue;
}
/**
* Returns a boolean value Jive property. If the property doesn't exist, the <tt>defaultValue</tt>
* will be returned.
*
* If the specified property can't be found, or if the value is not a number, the
* <tt>defaultValue</tt> will be returned.
*
* @param name the name of the property to return.
* @param defaultValue value returned if the property doesn't exist.
* @return true if the property value exists and is set to <tt>"true"</tt> (ignoring case).
* Otherwise <tt>false</tt> is returned.
*/
public static boolean getBooleanProperty(String name, boolean defaultValue) {
String value = getXMLProperty(name);
if (value != null) {
return Boolean.valueOf(value);
}
else {
return defaultValue;
}
}
/**
* Deletes a locale property. If the property doesn't exist, the method
* does nothing.
*
* @param name the name of the property to delete.
*/
public static void deleteXMLProperty(String name) {
if (xmlProperties == null) {
loadSetupProperties();
}
xmlProperties.deleteProperty(name);
}
/**
* Allows the name of the local config file name to be changed. The
* default is "manager.xml".
*
* @param configName the name of the config file.
*/
public static void setConfigName(String configName) {
JIVE_CONFIG_FILENAME = configName;
}
/**
* Returns the name of the local config file name.
*
* @return the name of the config file.
*/
static String getConfigName() {
return JIVE_CONFIG_FILENAME;
}
/**
* Loads properties if necessary. Property loading must be done lazily so
* that we give outside classes a chance to set <tt>home</tt>.
*/
private synchronized static void loadSetupProperties() {
if (xmlProperties == null) {
// If home is null then log that the application will not work correctly
if (home == null && !failedLoading) {
failedLoading = true;
StringBuilder msg = new StringBuilder();
msg.append("Critical Error! The home directory has not been configured, \n");
msg.append("which will prevent the application from working correctly.\n\n");
System.err.println(msg.toString());
}
// Create a manager with the full path to the xml config file.
else {
try {
xmlProperties = new XMLProperties(home + File.separator + getConfigName());
}
catch (IOException ioe) {
Log.error(ioe);
failedLoading = true;
}
}
}
}
}