diff --git a/src/gov/nasa/worldwind/Configuration.java b/src/gov/nasa/worldwind/Configuration.java index 654d3c034f..4fff2aef6a 100644 --- a/src/gov/nasa/worldwind/Configuration.java +++ b/src/gov/nasa/worldwind/Configuration.java @@ -256,6 +256,11 @@ public static synchronized String getStringValue(String key, String defaultValue public static synchronized String getStringValue(String key) { Object o = getInstance().properties.getProperty(key); + + if( o != null && o instanceof String ) + { + o = WWUtil.replacePropertyReferences((String)o); + } return o != null ? o.toString() : null; } diff --git a/src/gov/nasa/worldwind/util/WWUtil.java b/src/gov/nasa/worldwind/util/WWUtil.java index 76d710bba2..d80041f5dd 100644 --- a/src/gov/nasa/worldwind/util/WWUtil.java +++ b/src/gov/nasa/worldwind/util/WWUtil.java @@ -6,6 +6,7 @@ package gov.nasa.worldwind.util; +import gov.nasa.worldwind.Configuration; import gov.nasa.worldwind.avlist.*; import gov.nasa.worldwind.geom.*; import gov.nasa.worldwind.geom.coords.UTMCoord; @@ -14,6 +15,7 @@ import java.lang.reflect.*; import java.nio.*; import java.text.*; +import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -22,6 +24,9 @@ */ public class WWUtil { + static final String JAVA_CONFIG_VARIABLE = "\\$\\{([-a-zA-Z0-9._]+)\\}"; + + static final Pattern propPattern = Pattern.compile(JAVA_CONFIG_VARIABLE); /** * Converts a specified string to an integer value. Returns null if the string cannot be converted. * @@ -1270,4 +1275,45 @@ public static void generateTriStripNormals(FloatBuffer vertices, IntBuffer indic normals.put(i3 + 2, (float) n3.z); } } + + /** + * Replace all instances of ${....} with the corresponding + * property defined in the {@link #org.nasa.worldwind.Configuration()} + * + * @param in string containing ${} to be replaced + * + * @return result of in after ${} replacement + */ + public final static String replacePropertyReferences(String in) + { + if(in == null || in.indexOf("${") == -1) return in; + String result = in; + + Matcher matcher = propPattern.matcher(result); + StringBuffer buf = new StringBuffer(); + while (matcher.find()) + { + String replaceStr = matcher.group(1); + + //Since the Configuration.getStringValue also uses this routine + //this will resolve any nested properties references + String prop = Configuration.getStringValue(replaceStr); + + //if it isn't in our Configuration, check if it is a system property + if (prop == null ) + //Make sure we expand any properties references in the property + prop = replacePropertyReferences(System.getProperty(replaceStr)); + if( prop == null ) + { + Logging.logger().warning(String.format("Failed to find property '%s' for '%s'\n", replaceStr, in)); + } + else + { + matcher.appendReplacement(buf, prop); + } + } + matcher.appendTail(buf); + result = buf.toString(); + return result; + } } diff --git a/src/gov/nasa/worldwind/util/WWXML.java b/src/gov/nasa/worldwind/util/WWXML.java index 80827c22a4..cf185a0b9d 100644 --- a/src/gov/nasa/worldwind/util/WWXML.java +++ b/src/gov/nasa/worldwind/util/WWXML.java @@ -816,7 +816,8 @@ public static String getText(Element context, String path, XPath xpath) try { - return xpath.evaluate(path, context); + String val = xpath.evaluate(path, context); + return WWUtil.replacePropertyReferences(val); } catch (XPathExpressionException e) { diff --git a/test/gov/nasa/worldwind/util/WWUtilTest.java b/test/gov/nasa/worldwind/util/WWUtilTest.java index ccbd10bfe0..6cab903955 100644 --- a/test/gov/nasa/worldwind/util/WWUtilTest.java +++ b/test/gov/nasa/worldwind/util/WWUtilTest.java @@ -6,10 +6,20 @@ package gov.nasa.worldwind.util; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import gov.nasa.worldwind.Configuration; +import gov.nasa.worldwind.util.WWUtil; import junit.framework.TestCase; + import org.junit.Test; +import java.io.ByteArrayOutputStream; import java.util.*; +import java.util.logging.Handler; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.logging.StreamHandler; /** * Unit tests for {@link WWUtil}. @@ -50,4 +60,43 @@ public void testParseTimeString() time = WWUtil.parseTimeString("invalid time"); TestCase.assertNull(time); } + + @Test + public void testReplacePropertyReferences() + { + //Test that we can resolve nested property references + //and properties defined at the system level + Configuration.setValue("a", "I am a"); + System.setProperty("b", "${a}"); + Configuration.setValue("c", "${a}, ${b}"); + String expanded = WWUtil.replacePropertyReferences("Prefix_${c}_Suffix"); + TestCase.assertEquals("Prefix_I am a, I am a_Suffix", expanded); + } + + @Test + public void testReplacePropertyReferencesLogging() + { + + //Test that we get a log message when the property doesn't exist + Logger logger = Logging.logger(); + + SimpleFormatter formatter = new SimpleFormatter(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Handler handler = new StreamHandler(out, formatter); + logger.addHandler(handler); + try + { + WWUtil.replacePropertyReferences("${property.does.not.exist}"); + handler.flush(); + String logMsg = out.toString(); + + assertNotNull(logMsg); + assertTrue(logMsg.contains("Failed to find property 'property.does.not.exist' for '${property.does.not.exist}'")); + } + finally + { + logger.removeHandler(handler); + } + } + }