/**
* settings.txt
file. The
* settings.txt
is a simple java property file that collects all
* parameters used in different modules.
*
* The SettingsReader provides methods to get the property keys and the
* corresponding values. The keys could be defined as combinations of single
* keys. Therefore it is possible to combine differen classes of keys. An
* example could be:
*
*
* * #SettingNotFoundException * error.code.100=Interner Fehler * error.code.101=Die Konfigurationsdatei konnte nicht geladen werden * * #PDFDocumentException * error.code.200=Das Dokument konnte nicht geladen werden * * #SignatureException * error.code.300=Die Signatur ist ung�ltig * * #NormalizeException * error.code.400=Die angegebene Version ist nicht bekannt * * normalizer.version=V01 * ** * The internal representation of the example above is: * *
* * .error| * |.code| * | |.200=Das Dokument konnte nicht geladen werden * | |.100=Interner Fehler * | |.400=Die angegebene Version ist nicht bekannt * | |.101=Die Konfigurationsdatei konnte nicht geladen werden * | |.300=Die Signatur ist ung�ltig * .normalizer| * |.version=V01 * ** * @author wlackner */ public class SettingsReader implements Serializable { /** * SVUID. */ private static final long serialVersionUID = -8754114172766023454L; /** * The system File separator char */ private static final String FILE_SEP = System.getProperty("file.separator"); // /** // * The system temp file path // */ // private static final String TEMP_FILE_PATH = // System.getProperty("java.io.tmpdir"); // /** // * The home path of the tomcat webaplication // */ // private static final String CATALINA_HOME = System.getProperty("catalina.home"); // /** // * The default application name used in templates, settings, jsp's etc. // */ // private static final String APPL_NAME = "pdf-as"; // private static final String APPL_NAME = "egiz"; /** * The config file path postfix */ private static final String CFG = "cfg"; /** * The file path postfix where certificates are stored */ private static final String CERT = "certificates"; /** * pdf-as internal properties resource path */ private static final String PDF_AS_PROP_RESOURCE = "/config/pdf-as.properties"; /** * internal help file */ private static final String HELP_TEXT_PROP_RESOURCE = "/config/help_text.properties"; // /** // * The web application path // */ // private static final String WEB_APPL_DIR = "webapps" + FILE_SEP + APPL_NAME + FILE_SEP; /** * The path of the resources repository. * *
* This usually contains sub directories for the templates, the configuration * files, etc. *
*/ public static String RESOURCES_PATH = null; /** * The path for temporary files. */ public static String TMP_PATH = null; /** * The path of the configuration directory. */ public static String CONFIG_PATH = null; /** * The path of the certificated directory. */ public static String CERT_PATH = null; // /** // * The application config path for the command line tool // */ // public static final String APPL_CONFIG_PATH = USER_DIR + FILE_SEP + CFG + // FILE_SEP; // // /** // * The application config path for the web application // */ // public static final String WEB_CONFIG_PATH = CATALINA_HOME + FILE_SEP + // WEB_APPL_DIR + CFG + FILE_SEP; // // /** // * The certificates path for the command line tool // */ // public static final String APPL_CERT_PATH = USER_DIR + FILE_SEP + CERT + // FILE_SEP; // // /** // * The certificates path for the cweb application // */ // public static final String WEB_CERT_PATH = CATALINA_HOME + FILE_SEP + // WEB_APPL_DIR + CERT + FILE_SEP; /** * The name of the default configuration file. The definition syntax is the * java property config syntax. */ public static final String CONFIG_FILE_DEFAULT_NAME = "config.properties"; /** * The name of the help text configuration file. The definition syntax is the * java property config syntax. */ // public static final String HELP_TEXT_FILE_DEFAULT_NAME = "help_text.properties"; /** * The java properties from the settings file. */ private Properties properties_ = null; /** * The settings reader instance. Used to make the class singleton. */ private static SettingsReader instance_ = null; /** * The reference to the settings file. */ private static String settingsFile_ = null; /** * The reference to the property representation of the settings file. */ private PropertyTree pTree_ = new PropertyTree(); /** * The log. */ private static final Log logger_ = LogFactory.getLog(SettingsReader.class); private static final String INTERNAL_RESOURCE_PATH = "/config/"; /** * Make this constructor private. Use the method * {@link SettingsReader#getInstance()}to get an instance from this class. * The only cause to do this is that the definition file should only be read * once while getting often this instance. The method throws an IOException if * the settings file could not be read. * * @param settingsFile * load this file, if thesettingsFile == null
the
* default settings ({@link SettingsReader#CONFIG_FILE_DEFAULT_NAME})
* file is used
* @throws SettingsException
* if the settings file could not be read
*/
private SettingsReader(String settingsFile) throws SettingsException
{
try
{
String cfg_path = CONFIG_PATH;
properties_ = new Properties();
if (settingsFile == null)
{
settingsFile = cfg_path + CONFIG_FILE_DEFAULT_NAME;
}
settingsFile_ = settingsFile;
if (logger_.isInfoEnabled())
{
File file = new File(settingsFile_);
logger_.debug("load Settings:" + file.getAbsolutePath());
// Properties sys_prop = System.getProperties();
// Enumeration prop_keys = sys_prop.propertyNames();
// while (prop_keys.hasMoreElements()) {
// String key = (String) prop_keys.nextElement();
// String value = sys_prop.getProperty(key);
// logger_.info(key + "=" + value);
// }
}
FileInputStream sfs = new FileInputStream(settingsFile_);
properties_.load(sfs);
// dferbas override with system props
properties_.load(SettingsReader.class.getResourceAsStream(PDF_AS_PROP_RESOURCE));
Properties help_prop = new Properties();
// FileInputStream hfs = new FileInputStream(cfg_path + HELP_TEXT_FILE_DEFAULT_NAME);
// help_prop.load(hfs);
help_prop.load(SettingsReader.class.getResourceAsStream(HELP_TEXT_PROP_RESOURCE));
// load properties from current package!
// properties_.load(getClass().getResourceAsStream(settingsFile_));
Enumeration prop_keys = properties_.propertyNames();
while (prop_keys.hasMoreElements())
{
String key = (String) prop_keys.nextElement();
String value = properties_.getProperty(key);
pTree_.setKeyValue(key, value);
}
prop_keys = help_prop.propertyNames();
while (prop_keys.hasMoreElements())
{
String key = (String) prop_keys.nextElement();
String value = help_prop.getProperty(key);
properties_.setProperty(key, value);
pTree_.setKeyValue(key, value);
}
}
catch (IOException e)
{
throw new SettingsException("Couldn't load settings from file " + settingsFile, e);
}
}
/**
* This method returns an synchronized instance of this class. The settings
* file is read only once using this class. This method returns the instance
* holding the definitions of the default settings file. Default file:
* {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}: "settings.txt"
*
* @return an instance of the SettingsReader
* @throws SettingsException
* if the default settings file could not be read
*/
public synchronized static SettingsReader getInstance() throws SettingsException
{
return getInstance(null);
}
/**
* Reloads the Settings file.
*
* * Subsequent calls to getInstance will return the new settings. *
* * @throws SettingsException f.e. */ public synchronized static void createInstance () throws SettingsException { instance_ = null; getInstance(); } /** * This method returns an synchronized instance of this class. The settings * file is read only once using this class. This method returns the instance * holding the definitions of the settingsFile. If the input param *settingsFile == null
the default settings file will be load.
* Default file: {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}:
* "settings.txt"
*
* If an instance of this class exist, the input param is ignored! The
* SettingsReader is singleton and therefore the first
* {@link SettingsReader#getInstance()}defines the settings file that has to
* be loaded. This means changes between a application lifecyle can not be
* done!
*
* @param settingsFile
* the settings file that should be load.
* @return an instance of the SettingsReader
* @throws SettingsException
* if the settings file could not be read
*/
private synchronized static SettingsReader getInstance(String settingsFile) throws SettingsException
{
if (instance_ == null)
{
int length = Utils.max(new int[] { RESOURCES_PATH.length(), TMP_PATH.length(), CONFIG_PATH.length(), CERT_PATH.length() });
logger_.info(StringUtils.repeat("*", length + 25));
logger_.info(" resources path = \"" + RESOURCES_PATH + "\"");
logger_.info(" configuration path = \"" + CONFIG_PATH + "\"");
logger_.info(" certstore path = \"" + CERT_PATH + "\"");
logger_.info(" temporary path = \"" + TMP_PATH + "\"");
logger_.debug(" file.encoding = \"" + System.getProperty("file.encoding") + "\"");
logger_.info(StringUtils.repeat("*", length + 25));
IAIK.addAsProvider();
ECCProvider.addAsProvider();
// Does not conform with PKIX, but is used by belgium citizen card
// log.info("Registering RDN \"SERIALNUMBER\" as " + ObjectID.serialNumber + ".");
RFC2253NameParser.register("SERIALNUMBER", ObjectID.serialNumber);
instance_ = new SettingsReader(settingsFile);
}
return instance_;
}
/**
* This method returns a property value to the corresponding key. If the key
* is not found in the property file a SettingNotFoundException is thrown.
*
* @param key
* get the value for that key in the property file
* @return the value of the property key.
* @throws SettingNotFoundException
* ErrorCode: 100
*/
public String getSetting(String key) throws SettingNotFoundException
{
String result = properties_.getProperty(key);
if (result == null)
{
String log_message = "Configuration key not found: '" + key + "'! Check '" + settingsFile_ + "' file.";
if (logger_.isWarnEnabled())
{
logger_.warn(log_message);
}
SettingNotFoundException snf = new SettingNotFoundException(log_message);
throw snf;
}
// if (logger_.isDebugEnabled())
// {
// logger_.debug("Get Property:" + key + "=" + result);
// }
return result;
}
// TODO in the next change request, the Setting system will be refactored
// this is just for testing purposes.
public void setSetting(String key, String value)
{
properties_.setProperty(key, value);
}
/**
* Relocates the relative file.
*
* @param file
* The relative file.
* @return Returns the usable file.
*/
public static String relocateFile(String file)
{
// if (isWeb())
// {
// return CATALINA_HOME + FILE_SEP + WEB_APPL_DIR + file;
// }
//
// return file;
return RESOURCES_PATH + file;
}
/**
* This method returns a property value to the corresponding key. If the key
* is not found in the property file the input param defaultValue is returned.
*
* @param key
* get the value for that key in the property file
* @param defaultValue
* the default value if the key is not found
* @return the value of the property key
*/
public String getSetting(String key, String defaultValue)
{
String result = properties_.getProperty(key);
if (result == null)
{
result = defaultValue;
}
// if (logger_.isDebugEnabled())
// {
// logger_.debug("Get Property:" + key + "=" + result);
// }
return result;
}
/**
* This method returns a property value to the corresponding key. If the key
* is not found in the property file the input param defaultKey is searched.
* If the default key is not found the input param defaultValue is returned.
*
* @param primaryKey
* get the value for that key in the property file
* @param defaultKey
* the default key that should be searched if the primaryKey is not
* found
* @param defaultValue
* the default value if the defaultKey is not found
* @return the value of the property key
*/
public String getSetting(String primaryKey, String defaultKey, String defaultValue)
{
String key = primaryKey;
String result = properties_.getProperty(key);
if (result == null)
{
key = defaultKey;
result = properties_.getProperty(key);
if (result == null)
{
result = defaultValue;
}
}
// if (logger_.isDebugEnabled())
// {
// logger_.debug("Get Property:" + key + "=" + result);
// }
return result;
}
/**
* This method returns an array of keys in the same hierarchy of the
* keyPrefix. The method search all keys in the property file that has the
* keyPrefix as leading substring. The Object[]
collects all
* sub keys without the keyPrefix.
*
* @param keyPrefix
* to search for sub keys
* @return alls keys starting with the keyPrefix
*/
public Vector getSettingKeys(String keyPrefix)
{
Vector keys = new Vector();
Enumeration names = properties_.propertyNames();
while (names.hasMoreElements())
{
String full_name = (String) names.nextElement();
if (full_name.indexOf(keyPrefix) == 0)
{
keys.add(full_name.substring(keyPrefix.length() + 1));
}
}
return keys;
}
/**
* If a property value is number (interger) this method extracts the value and
* convert it to an int. If the key ist not found or the conversion fails, the
* defaultValue is returned.
*
* @param key
* get the value for that key in the property file
* @param defaultValue
* the default value if the key is not found
* @return the int value of the property key
*/
public int getIntSetting(String key, int defaultValue)
{
int int_property = defaultValue;
String value = null;
try
{
value = getSetting(key);
int_property = Integer.parseInt(value);
}
catch (NumberFormatException e)
{
if (logger_.isWarnEnabled())
{
logger_.warn("Can not convert " + value + " to int.", e);
}
}
catch (SettingNotFoundException e)
{
if (logger_.isWarnEnabled())
{
logger_.warn("Setting " + key + " not found, return default value:" + defaultValue, e);
}
}
return int_property;
}
/**
* This method returns an array of sub keys (children references) of the key.
* The method is a wrapper calling the method
* {@link PropertyTree#getKeys(String key)}.
*
* @param key
* get all sub keys for that key in the property file
* @return an list of sub keys (type String)
* @see PropertyTree
*/
public ArrayList getKeys(String key)
{
return pTree_.getKeys(key);
}
/**
* This method returns a the first value from a key. This means the method
* search in the PropertyTree representation of the config file. The
* PropertyTree class can overload key value paires. But the config file can
* not overload keys. If a key is defined more than one times the last
* definition is stored it the property list. The method is a wrapper calling
* the method {@link PropertyTree#getFirstValue(String key)}.
*
* @param key
* get the value for that key in the property file
* @return the value of the property key
* @see PropertyTree
*/
public String getValueFromKey(String key)
{
String value = pTree_.getFirstValue(key);
// if (logger_.isDebugEnabled())
// {
// logger_.debug("getValueFromKey:" + key + "=" + value);
// }
return value;
}
/**
* This method returns the PropertyTree representation of the configuration
* file.
*
* @return Returns the pTree.
* @see PropertyTree
*/
public PropertyTree getPTree()
{
return pTree_;
}
/**
* Reads internal resource as string.
* @param relativePath
* @return null in case of error
*/
public String readInternalResourceAsString(String relativePath) {
// return readAsString(getInternalResource(relativePath));
return FileHelper.readFromInputStream(getInternalResource(relativePath));
}
/**
* Get resource as stream, relative to internal resource path {@value #INTERNAL_RESOURCE_PATH}
*
* @param relativePath
* @return
*/
public InputStream getInternalResource(String relativePath) {
// kill starting "." and "./" in resource path
relativePath = StringUtils.removeStart(relativePath, ".");
relativePath = StringUtils.removeStart(relativePath, "/");
String streamURI = INTERNAL_RESOURCE_PATH + relativePath;
logger_.trace("Trying to get stream from \"" + streamURI + "\".");
InputStream stream = this.getClass().getResourceAsStream(streamURI);
if (stream == null) {
logger_.trace("Could not get stream.");
} else {
logger_.trace("Got stream.");
}
return stream;
}
/**
* Read resource as utf8 string.
* @param is
* @return null
in case of error
*/
/*
public String readAsString(InputStream is) {
if (is == null) return null;
try {
return IOUtils.toString(is, "utf-8");
} catch (IOException e) {
logger_.info("error reading stream to string ", e);
}
return null;
}
*/
// /**
// * This method checks the application context.
// *
// * @return true if the application is running in a webinterface, false
// * otherwise
// */
// public static boolean isWeb()
// {
// return CATALINA_HOME != null;
// }
/**
* Assembles the File of the temporary directory without checking if it really
* exists.
* @see TempDirHelper#assembleTemporaryDirectoryFile()
*/
protected static File assembleTemporaryDirectoryFile()
{
return TempDirHelper.assembleTemporaryDirectoryFile();
}
/**
* Returns the directory where temporary files should be stored.
*
* * If the directory doesn't exist, it is created. *
* * @return Returns the directory where temporary files should be stored. * @see TempDirHelper#getTemporaryDirectory() */ public static File getTemporaryDirectory() { return TempDirHelper.getTemporaryDirectory(); } /** * Deletes all files in the temporary directory, if it exists. * ** This should be used to clear temporary files when the application shuts * down. *
* @see TempDirHelper#clearTemporaryDirectory() */ public static void clearTemporaryDirectory() { TempDirHelper.clearTemporaryDirectory(); } public static synchronized void initialize(String configdir, String tmpdir) { String defaultConfigDeployedTo = null; // resolve work directory // configuration explicitely given ? if (configdir == null) { // configuration via system property ? logger_.debug("No configuration directory given. Looking for system property \"" + Constants.CONFIG_DIR_SYSTEM_PROPERTY + "\"."); configdir = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY); if (configdir == null) { // configuration via user's home directory ? logger_.debug("System property not set. Trying to locate configuration within the user's home directory."); String userHome = System.getProperty("user.home"); if (userHome == null || userHome.length() == 0) { throw new RuntimeException("Unable to resolve user's home directory."); } configdir = ConfigUtils.assertFileSeparator(userHome) + Constants.USERHOME_CONFIG_FOLDER; try { defaultConfigDeployedTo = ConfigUtils.deployDefaultConfiguration(configdir, false); } catch (ConfigUtilsException e) { throw new RuntimeException(e); } if (defaultConfigDeployedTo != null) { logger_.info("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **"); } else { logger_.debug("Default configuration has NOT been deployed. Maybe the configuration already exists."); } } else { logger_.debug("Configuration set by system property."); if (tmpdir == null) { tmpdir = configdir; } } } else { logger_.debug("Configuration path explicitely set."); } File configdirFile = new File(StrSubstitutor.replaceSystemProperties(configdir)); try { configdir = ConfigUtils.assertFileSeparator(configdirFile.getCanonicalPath()); } catch (IOException e) { configdir = ConfigUtils.assertFileSeparator(configdirFile.getPath()); } if (!configdirFile.isDirectory()) { throw new IllegalArgumentException("The config directory \"" + configdir + "\" does not exist or is not a directory."); } // resolve temporary dir if (tmpdir == null) { logger_.debug("Temporary directory not explicitely set. Looking for user's temp directory."); tmpdir = System.getProperty("java.io.tmpdir"); if (tmpdir == null) { logger_.debug("Unable to resolve user's temporary directory. Assuming temporary directory located within config dir."); tmpdir = configdir; } } else { logger_.debug("Temporary directory explicitely set."); } File tmpdirFile = new File(StrSubstitutor.replaceSystemProperties(ConfigUtils.assertFileSeparator(tmpdir) + Constants.TEMP_DIR_NAME)); try { tmpdir = ConfigUtils.assertFileSeparator(tmpdirFile.getCanonicalPath()); } catch (IOException e) { tmpdir = ConfigUtils.assertFileSeparator(tmpdirFile.getPath()); } RESOURCES_PATH = configdir; TMP_PATH = tmpdir; CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP; CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP; // ConfigUtils.printConfigInfo(logger_); if (defaultConfigDeployedTo != null) { logger_.debug("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **"); } logger_.debug("Setting system property \"" + Constants.CONFIG_DIR_SYSTEM_PROPERTY + "\" to \"" + configdirFile.getPath() + "\"."); System.setProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY, configdirFile.getPath()); } public static void initialize(String base_dir) { initialize(base_dir, null); } /** * Initializes the paths of the SettingsReader for web application usage. * * @param base_dir * The base directory of this web application. E.g. * TOMCAT_HOME/webapps/pdf-as */ public static void initializeForWeb(String base_dir) { initialize(base_dir, base_dir); } /** * Initializes the paths of the SettingsReader for commanline usage. */ public static void initializeForCommandLine() { initialize(null); } static { String versionString = "* PDF-AS library version " + PdfAS.PDFAS_VERSION + " *"; String paddingString = StringUtils.repeat("*", versionString.length()); logger_.info("PDF-AS info\n" + paddingString + "\n" + versionString + "\n" + paddingString); } }