From db52e4d66d60184d53a27ba4d6772461daacc03d Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 22 Mar 2013 08:57:51 +0000 Subject: Maintenance update (bugfixes, new features, cleanup...) Refer to /dok/RELEASE_NOTES-3.3.txt for further information. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/pdf-as/trunk@931 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../egov/egiz/cfg/CircularIncludeException.java | 44 ++++ .../wag/egov/egiz/cfg/NestedProperties.java | 255 +++++++++++++++++++++ .../knowcenter/wag/egov/egiz/cfg/PropertyTree.java | 82 +++++-- .../wag/egov/egiz/cfg/SettingsReader.java | 207 +++++++++-------- 4 files changed, 463 insertions(+), 125 deletions(-) create mode 100644 pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java create mode 100644 pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg') diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java new file mode 100644 index 0000000..6ff7d3a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java @@ -0,0 +1,44 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.knowcenter.wag.egov.egiz.cfg; + +/** + * Exception indicating that circular includes were detected. + * + * @author Datentechnik Innovation GmbH + * + */ +public class CircularIncludeException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CircularIncludeException() { + super(); + } + + public CircularIncludeException(String message) { + super(message); + } + +} diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java new file mode 100644 index 0000000..259a1dc --- /dev/null +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java @@ -0,0 +1,255 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.knowcenter.wag.egov.egiz.cfg; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Iterator; +import java.util.Properties; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.filefilter.WildcardFileFilter; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Enhanced Java Properties allowing nested include instructions.
+ * In order to include further Properties use the following instruction: + *

+ * include = [path/to/]foo.properties + *

+ * Note that wildcard imports are allowed, e.g. + *

+ * include = [path/to/]profile.*.properties + *

+ * In order to use more than one include instruction within a file append an arbitary postfix to include. + * in order to make each include key unique within a properties file, e.g. + *

+ * include = profile.SIGNATURBLOCK*.properties
+ * include.amtssignaturen = profile.AMTSSIGNATURBLOCK*.properties
+ * include.1 = myProfiles1/*.properties
+ * include.2 = myProfiles2/*.properties + *

+ * Note that + *

+ *

+ * Mind creating circular includes! + * + * @author Datentechnik Innovation GmbH + */ +public class NestedProperties extends Properties { + + private static final long serialVersionUID = 1L; + + private Log log = LogFactory.getLog(getClass()); + + /** + * Creates an empty property list with no default values. + */ + public NestedProperties() { + super(); + } + + /** + * Creates an empty property list with the specified defaults. + * @param defaults The defaults. + */ + public NestedProperties(Properties defaults) { + super(defaults); + } + + /** + * The name of the key that triggers including of other properties. + */ + private final String INCLUDE_KEY_NAME = "include"; + + /** + * Defines the default behaviour of the file matching filter. + */ + private final IOCase DEFAULT_IOCASE = IOCase.SENSITIVE; + + /** + * The maximum depth of includes before being regarded as circular (throwing a {@link CircularIncludeException}). + */ + private final int MAX_NESTED_INCLUDE_DEPTH = 25; + + @Override + /** + * Warning: When Properties are loaded using InputStreams include instructions are not supported. + */ + public synchronized void load(InputStream inStream) throws IOException { + log.debug("Loading properties from input stream. Include instructions are not supported."); + super.load(inStream); + } + + @Override + public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException { + // Loading from InputStream is not supported since including further property files that have been declared + // using relative paths need a context directory which cannot be retrieved from InputStreams. + throw new UnsupportedOperationException("Imports from XML files are not supported."); + } + + /** + * Reads a property list from a certain file including other properties files if include instructions are present. + * Note that include instructions that do not match any files do not result in an exception. A respective message at + * WARN level is logged. + * + * @param file + * The file to be read. + * @throws IOException + * Thrown in case of an I/O error. + * @throws CircularIncludeException + * Thrown if circular includes have been detected (@link {@link RuntimeException}). + */ + public synchronized void load(File file) throws IOException, CircularIncludeException { + load(file, 0); + } + + /** + * Reads a property list from a certain file including other properties files if include instructions are present. + * Note that include instructions that do not match any files do not result in an exception. A respective message at + * WARN level is logged. + * + * @param file + * The file to be read. + * @param currentDepth + * The current include depth. + * @throws IOException + * Thrown in case of an I/O error. + * @throws CircularIncludeException + * Thrown if circular includes have been detected (@link {@link RuntimeException}). + */ + private synchronized void load(File file, int currentDepth) throws IOException, CircularIncludeException { + if (currentDepth > MAX_NESTED_INCLUDE_DEPTH) { + throw new CircularIncludeException("Circular include instruction(s) detected."); + } + InputStream in = null; + try { + in = new FileInputStream(file); + log.debug("Loading '" + file.getCanonicalPath() + "'."); + super.load(in); + } finally { + IOUtils.closeQuietly(in); + } + // Properties have been loaded. Apply preprocessing step in order to process include instructions. + // Provide a context directory in order to be able to resolve relative path instructions. + processIncludes(file.getParentFile(), currentDepth); + } + + /** + * Resolves all include instructions as part of a postprocessing step. + * + * @param contextFolder + * The folder that should be assumed as starting folder for relative include instructions. + * @param currentDepth + * The current include depth. + * @throws IOException + * Thrown in case of error. + */ + private void processIncludes(File contextFolder, int currentDepth) throws IOException { + SortedMap sortedIncludeInstructions = new TreeMap(); + + // Walk through properties, collecting include instructions. + // Since the backing Hashtable does not guarantee any order, import instructions need to be sorted according to + // their keys (natural order -> alphabetically). + // This allows for defining a pseudo load order: include.1=path/to/settings.propertes, + // include.2=other/path/to/settings.properties + @SuppressWarnings("unchecked") + Enumeration propertyNames = (Enumeration) propertyNames(); + while (propertyNames.hasMoreElements()) { + String key = propertyNames.nextElement(); + // valid include instructions: include=xxx, include.foo=xxx, include.foo.foo=xxx... (keys are case + // insensitive) + if (INCLUDE_KEY_NAME.equalsIgnoreCase(key) || StringUtils.startsWithIgnoreCase(key, INCLUDE_KEY_NAME + ".")) { + String includeValue = StringUtils.trimToNull(getProperty(key)); + if (includeValue != null) { + sortedIncludeInstructions.put(key, includeValue); + } + } + } + + // performing imports + Iterator includeIt = sortedIncludeInstructions.keySet().iterator(); + while (includeIt.hasNext()) { + String includeInstructionKey = includeIt.next(); + String includePath = getProperty(includeInstructionKey); + processInclude(contextFolder, includePath, currentDepth); + // remove import instruction from properties + remove(includeInstructionKey); + } + } + + /** + * Processes a single include instruction (which may lead to several imports due to wildcard support). + * + * @param contextFolder + * The folder that should be assumed as starting folder for relative include instructions. + * @param includePath + * The include path instruction. + * @param currentDepth + * The current include depth. + * @throws IOException + * Thrown in case of error. + */ + private void processInclude(File contextFolder, String includePath, int currentDepth) throws IOException { + // Combine contextFolder with relative path instructions from includePath. + File includeInstruction = new File(contextFolder, includePath); + contextFolder = includeInstruction.getParentFile(); + String includeName = includeInstruction.getName(); + + WildcardFileFilter fileFilter = new WildcardFileFilter(includeName, DEFAULT_IOCASE); + Collection includeFiles = null; + if (contextFolder != null && contextFolder.exists() && contextFolder.isDirectory()) { + includeFiles = FileUtils.listFiles(contextFolder, fileFilter, null); + } + if (includeFiles != null && !includeFiles.isEmpty()) { + log.info("Including '" + includePath + "'."); + for (File includeFile : includeFiles) { + NestedProperties includeProperties = new NestedProperties(); + includeProperties.load(includeFile, currentDepth + 1); + putAll(includeProperties); + } + } else { + log.warn("Unable to find '" + includeName + "' in folder '" + contextFolder.getCanonicalPath() + "'."); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java index 49ba003..e9276b8 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java @@ -38,7 +38,7 @@ import java.util.Vector; * the values of a configuration is stored in nested hashes. The keys in an area are stored in a * HashMap. The values of a key are stored in a Vector to overload some keys. The property tree can * be used to extract sub nodes and sub keys of different tree levels. - * + * * @author wlackner * @see java.util.HashMap * @see java.util.Vector @@ -49,7 +49,7 @@ public class PropertyTree implements Serializable { * SVUID. */ private static final long serialVersionUID = -1686170519955886222L; - + /** * The key split string. A key can be a complex key. Sub keys are separated from each other with * the split string. This string is used to devide the complex key. @@ -77,7 +77,7 @@ public class PropertyTree implements Serializable { * the tree will be created. The last part of the key (last splitted element) adds the value to * there own value data structure (Vector).
* Example: setKeyValue("key.1_level.2_level","the value for k_1_2")null if the key is not a subtree referece */ @@ -129,7 +129,7 @@ public class PropertyTree implements Serializable { * This method return the subtree that corresponds to a particular key. The key does not split. * Therefore the key must be a children of the current node. Search only in the key map of the * current node. - * + * * @param key the key that has to be a sub node * @return a sub tree (PropertyTree) or null if the key is not a children of the * current node @@ -142,7 +142,7 @@ public class PropertyTree implements Serializable { * Returns the last value (keys can be overloaded) of a key. The key are splitted into subnodes * and the last node of the key is the current value holder. If a key or subnode is not in the sub * tree the return value is null. - * + * * @param key the key that holds the value (can be a nested key like "key.1.2.3") * @return the value of the key (last node of the key) or null otherwise */ @@ -162,7 +162,7 @@ public class PropertyTree implements Serializable { * Returns the first value (keys can be overloaded) of a key. The key are splitted into subnodes * and the last node of the key is the current value holder. If a key or subnode is not in the sub * tree the return value is null. - * + * * @param key the key that holds the value (can be a nested key like "key.1.2.3") * @return the value of the key (last node of the key) or null otherwise */ @@ -180,7 +180,7 @@ public class PropertyTree implements Serializable { /** * This method return all values of the current node. The values are stored as String values. - * + * * @return the values (type String) of the current node * @see Vector */ @@ -191,7 +191,7 @@ public class PropertyTree implements Serializable { /** * This method return all keys (sub tree references) of the current node as a Map. The keys are * stored as String values. - * + * * @return the keys (type String) of the current node * @see Map */ @@ -202,7 +202,7 @@ public class PropertyTree implements Serializable { /** * This method return all keys (sub tree references) of the current node as an ArrayList. The keys * are stored as String values. - * + * * @return the keys (type String) of the current node * @see ArrayList */ @@ -219,10 +219,10 @@ public class PropertyTree implements Serializable { } /** - * + * * This method return all sub tree references of a key as an ArrayList. The keys are stored as * String values. - * + * * @param key (can be a nested key like "key.1.2.3") * @return the keys (type String) of the current node * @see ArrayList @@ -237,7 +237,7 @@ public class PropertyTree implements Serializable { /** * This method return all values of a key. The values are stored as String values. - * + * * @param key (can be a nested key like "key.1.2.3") * @return the values (type Vector) of the key or null if the key is not in the sub * tree of the current node @@ -254,7 +254,7 @@ public class PropertyTree implements Serializable { /** * Store a sub tree (type PropertyTree) in the current node. The key and it's sub tree are stored * in a HashMap. - * + * * @param key the reference of the sub tree * @param tree the sub tree of the key * @see HashMap @@ -270,7 +270,7 @@ public class PropertyTree implements Serializable { * Extracts a sub tree of a nested key. The Method returns the last sub tree of the nested key. * Example: if the key is like: key.1.2.3 the sub tree of the last * node 3 is returned. - * + * * @param key the reference of the sub tree * @return a sub tree of the key or null if the key can not be found */ @@ -280,7 +280,7 @@ public class PropertyTree implements Serializable { /** * This method checks if a key is a reference to a sub tree in the current node. - * + * * @param key a simple key that is a parent reference of a sub tree * @return true if the key is found, false otherwise */ @@ -291,7 +291,7 @@ public class PropertyTree implements Serializable { /** * The default toString method. It starts with the current node recursively downwards and return * the String representation of the node. - * + * * @return the string representation of the node */ public String toString() { @@ -300,9 +300,9 @@ public class PropertyTree implements Serializable { /** * This is a helper function to define the prefix for different levels in the toString method, not - * realy nice ;-). - * It replaces all "." chars with " ". - * + * realy nice ;-).

+ * In other words: Fills {@code key} with spaces (of same length). + * * @param key * @return a replaces prefix string */ @@ -312,7 +312,7 @@ public class PropertyTree implements Serializable { /** * This method concatenates all values of the current node and return them as a combinded string. - * + * * @param prefix * @param tree * @return the string representation of the node values @@ -330,7 +330,7 @@ public class PropertyTree implements Serializable { /** * The toString method. It starts with a special level prefix, sub tree and recursively adds all * sub trees. - * + * * @param prefix the prefix for this node * @param tree the current node * @return the string representation of the node @@ -351,8 +351,40 @@ public class PropertyTree implements Serializable { } return os; } - + public void removeEntry(String key) { - this.keys_.remove(key); + this.keys_.remove(key); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((keys_ == null) ? 0 : keys_.hashCode()); + result = prime * result + ((values_ == null) ? 0 : values_.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PropertyTree other = (PropertyTree) obj; + if (keys_ == null) { + if (other.keys_ != null) + return false; + } else if (!keys_.equals(other.keys_)) + return false; + if (values_ == null) { + if (other.values_ != null) + return false; + } else if (!values_.equals(other.values_)) + return false; + return true; + } + } \ No newline at end of file diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java index 352c594..832f952 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java @@ -32,7 +32,6 @@ import iaik.security.provider.IAIK; import iaik.utils.RFC2253NameParser; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; @@ -42,6 +41,7 @@ import java.util.Enumeration; import java.util.Properties; import java.util.Vector; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.text.StrSubstitutor; import org.apache.commons.logging.Log; @@ -49,6 +49,7 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.pdfas.api.commons.Constants; import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException; +import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.gv.egiz.pdfas.utils.ConfigUtils; import at.gv.egiz.pdfas.utils.TempDirHelper; import at.knowcenter.wag.egov.egiz.PdfAS; @@ -61,36 +62,36 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper; * The SettingsReader reads the 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|
@@ -100,10 +101,10 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper;
  *                              |     |.101=Die Konfigurationsdatei konnte nicht geladen werden
  *                              |     |.300=Die Signatur ist ungueltig
  *                       .normalizer|
- *                                  |.version=V01      
- *      
+ *                                  |.version=V01
+ *
  * 
- * + * * @author wlackner */ public class SettingsReader implements Serializable @@ -145,17 +146,22 @@ public class SettingsReader implements Serializable * 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"; - + + /** + * The default configuration properties. These settings can be overridden by any local configuration. + */ + private static final String DEFAULT_CFG_PROPERTIES_RESOURCE = "/config/defaultconfig.properties"; + /** * internal help file */ private static final String HELP_TEXT_PROP_RESOURCE = "/config/help_text.properties"; - + public static final boolean REGISTER_IAIK_PROVIDERS_ON_DEFAULT = true; // /** @@ -165,14 +171,14 @@ public class SettingsReader implements Serializable /** * 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. */ @@ -237,7 +243,7 @@ public class SettingsReader implements Serializable /** * The reference to the settings file. */ - private static String settingsFile_ = null; + private static File settingsFile_ = null; /** * The reference to the property representation of the settings file. @@ -258,7 +264,7 @@ public class SettingsReader implements Serializable * 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 the settingsFile == null the * default settings ({@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}) @@ -271,39 +277,45 @@ public class SettingsReader implements Serializable 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); - + settingsFile_ = new File(settingsFile); + logger_.debug("load Settings:" + settingsFile_.getAbsolutePath()); + + // DTI + // (1) first load default properties which may be overloaded by local configurations + Properties defaultConfiguration = new Properties(); + InputStream in = null; + try { + defaultConfiguration.load(in = getClass().getResourceAsStream(DEFAULT_CFG_PROPERTIES_RESOURCE)); + } catch (Exception e) { + throw new SettingsException(ErrorCode.UNABLE_TO_LOAD_DEFAULT_CONFIG, + "Unable to load default configuration.", e); + } finally { + IOUtils.closeQuietly(in); + } + + // (2) then load main configuration (considers include instructions) + NestedProperties includeAwareProperties = new NestedProperties(defaultConfiguration); + try { + includeAwareProperties.load(settingsFile_); + properties_ = includeAwareProperties; + } catch (CircularIncludeException e) { + throw new SettingsException(ErrorCode.CIRCULAR_INCLUDE_INSTRUCTION_DETECTED, e); + } + + // (3) then forcedly overwrite some system settings // dferbas override with system props properties_.load(SettingsReader.class.getResourceAsStream(PDF_AS_PROP_RESOURCE)); + // (4) and finally add help texts. 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_)); + // (5) Build PropertyTree configuration. Enumeration prop_keys = properties_.propertyNames(); - while (prop_keys.hasMoreElements()) { String key = (String) prop_keys.nextElement(); @@ -319,10 +331,12 @@ public class SettingsReader implements Serializable pTree_.setKeyValue(key, value); } } + catch (IOException e) { throw new SettingsException("Couldn't load settings from file " + settingsFile, e); } + } /** @@ -331,7 +345,7 @@ public class SettingsReader implements Serializable * holding the definitions of the default settings file. Default file: * {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}: "settings.txt". * Note: IAIK JCE and IAIK ECC security providers are automatically registered. - * + * * @return an instance of the SettingsReader * @throws SettingsException * if the default settings file could not be read @@ -340,15 +354,15 @@ public class SettingsReader implements Serializable { return getInstance(null); } - + /** * Reloads the Settings file. - * + * *

* Subsequent calls to getInstance will return the new settings. * Note: IAIK JCE and IAIK ECC security providers are automatically registered. *

- * + * * @throws SettingsException f.e. */ public synchronized static void createInstance() throws SettingsException @@ -356,16 +370,16 @@ public class SettingsReader implements Serializable instance_ = null; getInstance(); } - + /** * Reloads the Settings file. - * + * *

* Subsequent calls to getInstance will return the new settings. *

* @param registerProvider true: automatically registers IAIK JCE and ECC Provider; * false: providers will NOT be automatically registered, providers - * needed have to be registered by the API user + * needed have to be registered by the API user * @throws SettingsException f.e. */ public synchronized static void createInstance(boolean registerProvider) throws SettingsException @@ -381,18 +395,18 @@ public class SettingsReader implements Serializable * 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. * @param registerProvider true: automatically registers IAIK JCE and ECC Provider; * false: providers will NOT be automatically registered, providers - * needed have to be registered by the API user + * needed have to be registered by the API user * @return an instance of the SettingsReader * @throws SettingsException * if the settings file could not be read @@ -402,7 +416,7 @@ public class SettingsReader implements Serializable 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 + "\""); @@ -410,7 +424,7 @@ public class SettingsReader implements Serializable logger_.info(" temporary path = \"" + TMP_PATH + "\""); logger_.debug(" file.encoding = \"" + System.getProperty("file.encoding") + "\""); logger_.info(StringUtils.repeat("*", length + 25)); - + if (registerProvider) { IAIK.addAsProvider(); ECCProvider.addAsProvider(); @@ -429,12 +443,12 @@ public class SettingsReader implements Serializable // 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 an synchronized instance of this class. The settings * file is read only once using this class. This method returns the instance @@ -443,13 +457,13 @@ public class SettingsReader implements Serializable * Default file: {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}: * "settings.txt". * Note: IAIK JCE and IAIK ECC security providers are automatically registered. - * + * * 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 @@ -464,7 +478,7 @@ public class SettingsReader implements Serializable /** * 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. @@ -490,17 +504,10 @@ public class SettingsReader implements Serializable 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. @@ -519,7 +526,7 @@ public class SettingsReader implements Serializable /** * 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 @@ -545,7 +552,7 @@ public class SettingsReader implements Serializable * 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 @@ -580,7 +587,7 @@ public class SettingsReader implements Serializable * 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 @@ -604,7 +611,7 @@ public class SettingsReader implements Serializable * 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 @@ -641,7 +648,7 @@ public class SettingsReader implements Serializable * 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) @@ -659,7 +666,7 @@ public class SettingsReader implements Serializable * 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 @@ -678,7 +685,7 @@ public class SettingsReader implements Serializable /** * This method returns the PropertyTree representation of the configuration * file. - * + * * @return Returns the pTree. * @see PropertyTree */ @@ -686,20 +693,20 @@ public class SettingsReader implements Serializable { 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)); +// 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 */ @@ -717,9 +724,9 @@ public class SettingsReader implements Serializable } return stream; } - + /** - * Read resource as utf8 string. + * Read resource as utf8 string. * @param is * @return null in case of error */ @@ -730,7 +737,7 @@ public class SettingsReader implements Serializable return IOUtils.toString(is, "utf-8"); } catch (IOException e) { logger_.info("error reading stream to string ", e); - } + } return null; } */ @@ -758,11 +765,11 @@ public class SettingsReader implements Serializable /** * 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() */ @@ -773,7 +780,7 @@ public class SettingsReader implements Serializable /** * Deletes all files in the temporary directory, if it exists. - * + * *

* This should be used to clear temporary files when the application shuts * down. @@ -784,19 +791,19 @@ public class SettingsReader implements Serializable { 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"); @@ -808,7 +815,7 @@ public class SettingsReader implements Serializable defaultConfigDeployedTo = ConfigUtils.deployDefaultConfiguration(configdir, false); } catch (ConfigUtilsException e) { throw new RuntimeException(e); - } + } if (defaultConfigDeployedTo != null) { logger_.info("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **"); } else { @@ -833,7 +840,7 @@ public class SettingsReader implements Serializable { 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."); @@ -851,14 +858,14 @@ public class SettingsReader implements Serializable } 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 + "\" **"); } @@ -870,10 +877,10 @@ public class SettingsReader implements Serializable { 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 @@ -890,14 +897,14 @@ public class SettingsReader implements Serializable { 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); } - + public Properties getProperties() { return this.properties_; } -- cgit v1.2.3