package org.igfay.jfig;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import org.igfay.util.PropertyUtility;
/**
* Abstract class to parse a configuration file. Concrete classes parse either
* XML or INI file. This class contains common logic to resolve symbolic and
* property variables.
*
*@author bconrad
*@created April 3, 2001
*/
public abstract class JFigParser {
private static Logger log = Logger.getLogger(JFigParser.class);
private static Logger logDetail = Logger.getLogger("ConfigDetail");
private JFigLocatorIF jfigLocator;
private static Pattern regexSubstitution;
private static Pattern regexGlobalSubstitution;
private static Pattern regexPropertyVariable;
private JFig config;
static {
PropertyUtility.setProperty(JFigConstants.PATH_SEPARATOR, PropertyUtility.getProperty("path.separator"));
}
/**
* Constructor to allow user to override configFileName default.
* Get the location from ConfigLocator
*
*@param configFileName Description of Parameter
*/
public JFigParser(JFig config, JFigLocatorIF jfigLocator) {
setConfig(config);
setJFigLocator(jfigLocator);
}
/**
* Returns the allConfigFiles.
* @return List
*/
public Map getAllConfigFiles() {
return getConfig().getAllConfigFiles();
}
/**
* processConfig
* @return Description of the Returned Value
*@exception JFigException Description of Exception
*/
protected abstract boolean processConfig() throws JFigException;
/**
* Resolve symbolic values in the configuration. This method is
* called after all configuration files have been parsed.
*
* Iterate through the dictionary and resolve values for each section/key.
*/
protected void resolveSymbolicValues() throws JFigException {
log.debug("");
Iterator sectionEnumeration = getConfigDictionary().getSectionIterator();
while (sectionEnumeration.hasNext()) {
String sectionName = (String) sectionEnumeration.next();
logDetail.debug("~! sectionName " + sectionName);
TreeMap sectionHashtable = getConfigDictionary().getSectionDictionary(sectionName);
Iterator keyEnumeration = sectionHashtable.keySet().iterator();
while (keyEnumeration.hasNext()) {
String key = (String) keyEnumeration.next();
String value = (String) sectionHashtable.get(key);
value = resolvePropertyVariables(sectionName, key, value);
resolveSymbolicValues(sectionName, key, value);
} // while keyEnumeration
} // while sectionEnumeration
log.debug("end resolveSymbolicValues()");
}
/**
* Replace all occurances of symbolic references with actual values. A
* symbolic reference looks like "&(section)key".
*
*@param section Description of Parameter
*@param key Description of Parameter
*@param value Description of Parameter
*/
private void resolveSymbolicValues(String section, String key, String value) throws JFigException {
logDetail.debug("section " + section + " key " + key + " value " + value);
if (value ==null ) {
return;
}
String replacementValue = null;
String replacementSection = null;
String replacementKey = null;
String start = null;
String rest = null;
// Save the value
String beforeValue = value;
// Loop through value while it has a symbolic reference
Matcher matcher = getRegexSubstitution().matcher(value);
while ( (value.indexOf(JFigConstants.SECTION_START_DELIMITER) >= 0)&& matcher.find()) {
logDetail.debug("~ foundMatch ");
//matcher = getRegexSubstitution().matcher(value);
// Get the values that we matched in our regular expression
start = matcher.group(1);
replacementSection = matcher.group(3);
// If the replacement section is the special keyword "section" then use the current section
if (replacementSection.equalsIgnoreCase("section")) {
replacementSection = section;
}
replacementKey = matcher.group(5);
rest = matcher.group(7);
logDetail.debug("~! rSection " + replacementSection + " rKey " + replacementKey);
// Get the value for the section/key that we are referencing
replacementValue = getConfigDictionary().getValue(replacementSection, replacementKey, "null");
logDetail.debug("~! rValue " + replacementValue);
// Substitute the reference with the new value.
value = start + replacementValue + rest;
logDetail.debug("~! value " + value);
matcher = getRegexSubstitution().matcher(value);
} // end while
// Set the new substituted value, if it has changed
if (!beforeValue.equals(value)) {
logDetail.debug("~!resolveSymbolicValues() replace " + beforeValue + " with " + value);
// put back the modified value.
getConfigDictionary().setConfigurationValue(section, key, value);
}
}
/**
* Replace all occurances of Property variables with properties.
* Property variable looks like "$PropertyVariable$".
*
*@param section Description of Parameter
*@param key Description of Parameter
*@param value Description of Parameter
*/
private String resolvePropertyVariables(String section, String key, String value) {
if (value == null) {
return null;
}
String replacementValue = null;
String replacementKey = null;
String start = null;
String rest = null;
// Save the value
String beforeValue = value;
// Loop through value while it has a symbolic reference
Matcher matcher = getRegexPropertyVariable().matcher(value);
while ((value.indexOf(JFigConstants.PROPERTY_DELIMITER) >= 0) && matcher.find()) {
logDetail.debug("~!section " + section + " key " + key + " value " + value);
// Get the values that we matched in our regular expression
start = matcher.group(1);
replacementKey = matcher.group(3);
rest = matcher.group(5);
logDetail.debug("~! -- rKey " + replacementKey + " rest: " + rest);
// Get the value for the section/key that we are referencing
replacementValue = PropertyUtility.getProperty(replacementKey, "");
logDetail.debug("~!rValue " + replacementValue);
// Substitute the reference with the new value.
value = start + replacementValue + rest;
logDetail.debug("~!resolvePropertyVariables value " + value);
matcher = getRegexPropertyVariable().matcher(value);
}
// end while
// Set the new substituted value, if it has changed
if (!beforeValue.equals(value)) {
logDetail.debug("~!replace " + beforeValue + " with\n\t" + value);
getConfigDictionary().setConfigurationValue(section, key, value);
// put back the modified value.
}
return value;
}
protected void addPropertyValues() {
log.debug("");
TreeMap map = getConfigDictionary().getSectionNamed("properties", false);
if (map != null) {
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String key = (String)iterator.next();
String value = (String)map.get(key);
PropertyUtility.setProperty(key,value);
}
}
}
protected JFigDictionary getConfigDictionary() {
return getConfig().getConfigDictionary();
}
protected String getConfigFileName() {
return getJFigLocator().getConfigFileName();
}
protected static Pattern getRegexPropertyVariable() {
if (regexPropertyVariable == null) {
regexPropertyVariable = Pattern.compile("(.*?)(\\"+JFigConstants.PROPERTY_DELIMITER+")(.*?)(\\"+JFigConstants.PROPERTY_DELIMITER+")(.*?)$", Pattern.MULTILINE);
}
return regexPropertyVariable;
}
protected static Pattern getRegexSubstitution() throws JFigException {
if (regexSubstitution == null) {
// ? sets to non-greedy. \\) says look for literal ")"
regexSubstitution = Pattern.compile("(.*)(\\" + JFigConstants.SECTION_START_DELIMITER + ")(.*?)(\\" +
JFigConstants.SECTION_END_DELIMITER+"?\\" + // 0 or 1 end section delimiter
JFigConstants.KEY_START_DELIMITER + ")(.*?)(\\" + JFigConstants.KEY_END_DELIMITER +
")(.*?)$", Pattern.MULTILINE);
}
return regexSubstitution;
}
// for convert
protected static Pattern getRegexGlobalSubstitution() throws JFigException {
if (regexGlobalSubstitution == null) {
// ? sets to non-greedy. \\) says look for literal ")"
regexGlobalSubstitution = Pattern.compile("(.*)(\\" + JFigConstants.SECTION_START_DELIMITER + ")(.*?)(\\" +
JFigConstants.SECTION_END_DELIMITER+"?\\" + // 0 or 1 end section delimiter
JFigConstants.KEY_START_DELIMITER + ")(.*?)(\\" + JFigConstants.KEY_END_DELIMITER +
")([.|\n|\r]*?)", Pattern.MULTILINE);
}
return regexGlobalSubstitution;
}
// protected void setConfigFileName(String configFileName) {
// this.configFileName = configFileName;
// log.info("configFileName " + configFileName);
// }
/**
* Returns the configLocation.
* @return String
*/
// public String getConfigLocation() {
// return getJFigLocator().getConfigLocation();
// }
/**
* Sets the configLocation.
* @param configLocation The configLocation to set
*/
// public void setConfigLocation(String configLocation) {
// this.configLocation = configLocation;
// }
/**
* @return
*/
public JFig getConfig() {
return config;
}
/**
* @param config
*/
public void setConfig(JFig config) {
this.config = config;
}
/**
* @return
*/
public JFigLocatorIF getJFigLocator() {
return jfigLocator;
}
/**
* @param locatorIF
*/
public void setJFigLocator(JFigLocatorIF locatorIF) {
jfigLocator = locatorIF;
}
}
|