| |
"Enabling Constant Substitution in Property Values"
Vol. 6, Issue 12, p. 52
Listing 1: Sample Properties
# Sample.properties
#
# These properties illustrate the use of constants
# within property values, accessed using the
# XProperties class.
# Use several levels of recursive substitution to
# define paths for different resource types
ROOT_DRIVE=c:
BASE_DIR={ROOT_DRIVE}/base
HTML_DIR={BASE_DIR}/html
XML_DIR={BASE_DIR}/xml
IMAGE_DIR={BASE_DIR}/image
# Define full pathnames for resource files
MyHtmlFile={HTML_DIR}/MyFile.html
MyXmlFile={XML_DIR}/MyFile.xml
NewImage={IMAGE_DIR}/new.gif
SaveImage={IMAGE_DIR}/save.gif
PrintImage={IMAGE_DIR}/print.gif
# Assemble a property value from several constants
PROTOCOL=https
SERVER=server.acme.com
PORT=80
RESOURCE=index.html
HomePageURL={PROTOCOL}//{SERVER}:{PORT}/{RESOURCE}
# Define a constant for each possible value
UNIT_TEST_URL = http://localhost:8080/abc
SYSTEM_TEST_URL = http://testserver.acme.com/abc
PRODUCTION_URL= http://prodserver.acme.com/abc
# Select from the possible values
MyURL = {UNIT_TEST_URL}
Listing 2: Sample Java Code to Use XProperties
// import java.io.*;
// Create an XProperties and load the property file
Properties prop = new XProperties();
InputStream in = new FileInputStream("Sample.properties");
prop.load(in);
// List the keys for the property values of interest
String[] keys = {
"MyHtmlFile", "MyXmlFile",
"NewImage", "SaveImage", "PrintImage",
"HomePageURL", "MyURL" };
// Iterate through the keys; display key and value
for (int i=0; i < keys.length; i++) {
String value = prop.getProperty(keys[i]);
System.out.println(keys[i]+" = "+value);
}
Listing 3: Resulting Output from Code in Listing 2
MyHtmlFile = c:/base/html/MyFile.html
MyXmlFile = c:/base/xml/MyFile.xml
NewImage = c:/base/image/new.gif
SaveImage = c:/base/image/save.gif
PrintImage = c:/base/image/print.gif
HomePageURL = https//server.acme.com:80/index.html
MyURL = http://localhost:8080/abc
Listing 4: Source Code for XProperties Class
import java.util.Properties;
/**
* A subclass of Properties that allows recursive
* references for property values. For example,
*
* <pre><code>
* A=12345678
* B={A}90
* C={B} plus more
* </code></pre>
*
* will result in <code>getProperty("C")</code>
* returning the value "1234567890 plus more".
*
* @author: Chris Mair
*/
public class XProperties extends Properties {
// The prefix and suffix for constant names
// within property values
private static final String START_CONST = "{";
private static final String END_CONST = "}";
// The maximum depth for recursive substitution
// of constants within property values
// (e.g., A={B} .. B={C} .. C={D} .. etc.)
private static final int MAX_SUBST_DEPTH = 5;
/**
* Creates an empty property list with no default
* values.
*/
public XProperties() {
super();
}
/**
* Creates an empty property list with the
* specified defaults.
* @param defaults java.util.Properties
*/
public XProperties(Properties defaults) {
super(defaults);
}
/**
* Searches for the property with the specified
* key in this property list. If the key is not
* found in this property list, the default
* property list, and its defaults, recursively,
* are then checked. The method returns
* <code>null</code> if the property is not found.
*
* @param key the property key.
* @return the value in this property list with
* the specified key value.
*/
public String getProperty(String key) {
// Return the property value starting at level 0
return getProperty(key, 0);
}
/**
* Searches for the property with the specified
* key in this property list. If the key is not
* found in this property list, the default
* property list, and its defaults, recursively,
* are then checked. The method returns
* <code>null</code> if the property is not found.
*
* <p>The level parameter specifies the current
* level of recursive constant substitution. If
* the requested property value includes a
* constant, its value is substituted in place
* through a recursive call to this method,
* incrementing the level. Once level exceeds
* MAX_SUBST_DEPTH, no further constant
* substitutions are performed within the
* current requested value.
*
* @param key the property key.
* @param level the level of recursion so far
* @return the value in this property list with
* the specified key value.
*/
private String getProperty(String key, int level) {
String value = super.getProperty(key);
if (value != null) {
// Get the index of the first constant, if any
int beginIndex = 0;
int startName = value.indexOf(START_CONST, beginIndex);
while (startName != -1) {
if (level+1 > MAX_SUBST_DEPTH) {
// Exceeded MAX_SUBST_DEPTH
// Return the value as is
return value;
}
int endName = value.indexOf(END_CONST, startName);
if (endName == -1) {
// Terminating symbol not found
// Return the value as is
return value;
}
String constName = value.substring(startName+1, endName);
String constValue = getProperty(constName, level+1);
if (constValue == null) {
// Property name not found
// Return the value as is
return value;
}
// Insert the constant value into the
// original property value
String newValue = (startName>0)
? value.substring(0, startName) : "";
newValue += constValue;
// Start checking for constants at this index
beginIndex = newValue.length();
// Append the remainder of the value
newValue += value.substring(endName+1);
value = newValue;
// Look for the next constant
startName = value.indexOf(START_CONST, beginIndex);
}
}
// Return the value as is
return value;
}
}
|
|