From 184d42edacdda1dd14d706e2c311baec58e50c5e Mon Sep 17 00:00:00 2001 From: rougeSE Date: Sat, 15 Oct 2016 06:20:30 -0600 Subject: [PATCH] All for property references in XML files When deploying Worldwind within an isolated environments with isloated WMS servers, there is no way to centralize the definition of the server name, instead, each of the layer XML files have to be updated. This change allows any of the WW XML file to contain a property reference, ${property.name}, and have these properties resolved when the text is retrieved. Properties can be defined in three different ways; 1)worldwind.xml , 2) Java system property (-Dproperty.name), or 3) using the legacy WW properties file. --- src/gov/nasa/worldwind/Configuration.java | 5 ++ src/gov/nasa/worldwind/util/WWUtil.java | 46 ++++++++++++++++++ src/gov/nasa/worldwind/util/WWXML.java | 3 +- test/gov/nasa/worldwind/util/WWUtilTest.java | 49 ++++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) 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); + } + } + }