View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.configuration2;
18  
19  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  
23  import java.awt.event.KeyEvent;
24  import java.net.InetAddress;
25  import java.util.Arrays;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
30  import org.apache.commons.lang3.SystemProperties;
31  
32  /**
33   * A helper class that defines a bunch of tests related to variable interpolation. It can be used for running these
34   * tests on different configuration implementations.
35   */
36  public final class InterpolationTestHelper {
37  
38      /**
39       * Tests accessing and manipulating the interpolator object.
40       *
41       * @param config the configuration to test
42       */
43      public static void testGetInterpolator(final AbstractConfiguration config) {
44          config.addProperty("var", "${echo:testVar}");
45          final ConfigurationInterpolator interpol = config.getInterpolator();
46          interpol.registerLookup("echo", varName -> "Value of variable " + varName);
47          assertEquals("Value of variable testVar", config.getString("var"));
48      }
49  
50      /**
51       * Tests obtaining a configuration with all variables replaced by their actual values.
52       *
53       * @param config the configuration to test
54       * @return the interpolated configuration
55       */
56      public static Configuration testInterpolatedConfiguration(final AbstractConfiguration config) {
57          config.setProperty("applicationRoot", "/home/applicationRoot");
58          config.setProperty("db", "${applicationRoot}/db/hypersonic");
59          config.setProperty("inttest.interpol", "${unknown.property}");
60          config.setProperty("intkey.code", "${const:java.awt.event.KeyEvent.VK_CANCEL}");
61          config.setProperty("inttest.sysprop", "${sys:java.version}");
62          config.setProperty("inttest.numvalue", "3\\,1415");
63          config.setProperty("inttest.value", "${inttest.numvalue}");
64          config.setProperty("inttest.list", "${db}");
65          config.addProperty("inttest.list", "${inttest.value}");
66  
67          final Configuration c = config.interpolatedConfiguration();
68          assertEquals("/home/applicationRoot/db/hypersonic", c.getProperty("db"));
69          assertEquals(KeyEvent.VK_CANCEL, c.getInt("intkey.code"));
70          assertEquals(SystemProperties.getJavaVersion(), c.getProperty("inttest.sysprop"));
71          assertEquals("3,1415", c.getProperty("inttest.value"));
72          final List<?> lst = (List<?>) c.getProperty("inttest.list");
73          assertEquals(Arrays.asList("/home/applicationRoot/db/hypersonic", "3,1415"), lst);
74          assertEquals("${unknown.property}", c.getProperty("inttest.interpol"));
75  
76          return c;
77      }
78  
79      /**
80       * Tests basic interpolation facilities of the specified configuration.
81       *
82       * @param config the configuration to test
83       */
84      public static void testInterpolation(final Configuration config) {
85          config.setProperty("applicationRoot", "/home/applicationRoot");
86          config.setProperty("db", "${applicationRoot}/db/hypersonic");
87          final String unInterpolatedValue = "${applicationRoot2}/db/hypersonic";
88          config.setProperty("dbFailedInterpolate", unInterpolatedValue);
89          final String dbProp = "/home/applicationRoot/db/hypersonic";
90  
91          assertEquals(dbProp, config.getString("db"));
92          assertEquals(unInterpolatedValue, config.getString("dbFailedInterpolate"));
93  
94          config.setProperty("arrayInt", "${applicationRoot}/1");
95          final String[] arrayInt = config.getStringArray("arrayInt");
96          assertEquals("/home/applicationRoot/1", arrayInt[0]);
97  
98          config.addProperty("path", Arrays.asList("/temp", "C:\\Temp", "/usr/local/tmp"));
99          config.setProperty("path.current", "${path}");
100         assertEquals("/temp", config.getString("path.current"));
101     }
102 
103     /**
104      * Tests interpolation of constant values.
105      *
106      * @param config the configuration to test
107      */
108     public static void testInterpolationConstants(final Configuration config) {
109         config.addProperty("key.code", "${const:java.awt.event.KeyEvent.VK_CANCEL}");
110         assertEquals(KeyEvent.VK_CANCEL, config.getInt("key.code"));
111         assertEquals(KeyEvent.VK_CANCEL, config.getInt("key.code"));
112     }
113 
114     /**
115      * Tests interpolation of environment properties.
116      *
117      * @param config the configuration to test
118      */
119     public static void testInterpolationEnvironment(final Configuration config) {
120         final Map<String, String> env = System.getenv();
121         for (final Map.Entry<String, String> e : env.entrySet()) {
122             config.addProperty("prop" + e.getKey(), "${env:" + e.getKey() + "}");
123         }
124 
125         for (final Map.Entry<String, String> e : env.entrySet()) {
126             assertEquals(e.getValue(), config.getString("prop" + e.getKey()), "Wrong value for environment property " + e.getKey());
127         }
128     }
129 
130     /**
131      * Tests whether a variable can be escaped, so that it won't be interpolated.
132      *
133      * @param config the configuration to test
134      */
135     public static void testInterpolationEscaped(final Configuration config) {
136         config.addProperty("var", "x");
137         config.addProperty("escVar", "Use the variable $${${var}}.");
138         assertEquals("Use the variable ${x}.", config.getString("escVar"));
139     }
140 
141     /**
142      * Tests interpolation of localhost properties.
143      *
144      * @param config the configuration to test
145      */
146     public static void testInterpolationLocalhost(final Configuration config) {
147         final String[] localhostKeys = {"name", "canonical-name", "address"};
148         final InetAddress localHost = assertDoesNotThrow(InetAddress::getLocalHost);
149         final String[] localhostValues = {localHost.getHostName(), localHost.getCanonicalHostName(), localHost.getHostAddress()};
150         for (int i = 0; i < localhostKeys.length; i++) {
151             config.addProperty("prop" + i, "${localhost:" + localhostKeys[i] + "}");
152         }
153 
154         for (int i = 0; i < localhostKeys.length; i++) {
155             assertEquals(localhostValues[i], config.getString("prop" + i), "Wrong value for system property " + localhostKeys[i]);
156         }
157     }
158 
159     /**
160      * Tests an invalid interpolation that results in an infinite loop. This loop should be detected and an exception should
161      * be thrown.
162      *
163      * @param config the configuration to test
164      */
165     public static void testInterpolationLoop(final Configuration config) {
166         config.setProperty("test.a", "${test.b}");
167         config.setProperty("test.b", "${test.a}");
168 
169         assertThrows(IllegalStateException.class, () -> config.getString("test.a"));
170     }
171 
172     /**
173      * Tests interpolation when a subset configuration is involved.
174      *
175      * @param config the configuration to test
176      */
177     public static void testInterpolationSubset(final Configuration config) {
178         config.addProperty("test.a", Integer.valueOf(42));
179         config.addProperty("test.b", "${test.a}");
180         assertEquals(42, config.getInt("test.b"));
181         final Configuration subset = config.subset("test");
182         assertEquals("42", subset.getString("b"));
183         assertEquals(42, subset.getInt("b"));
184     }
185 
186     /**
187      * Tests interpolation of system properties.
188      *
189      * @param config the configuration to test
190      */
191     public static void testInterpolationSystemProperties(final Configuration config) {
192         final String[] sysProperties = {"java.version", "java.vendor", "os.name", "java.class.path"};
193         for (int i = 0; i < sysProperties.length; i++) {
194             config.addProperty("prop" + i, "${sys:" + sysProperties[i] + "}");
195         }
196 
197         for (int i = 0; i < sysProperties.length; i++) {
198             assertEquals(System.getProperty(sysProperties[i]), config.getString("prop" + i), "Wrong value for system property " + sysProperties[i]);
199         }
200     }
201 
202     /**
203      * Tests interpolation when the referred property is not found.
204      *
205      * @param config the configuration to test
206      */
207     public static void testInterpolationUnknownProperty(final Configuration config) {
208         config.addProperty("test.interpol", "${unknown.property}");
209         assertEquals("${unknown.property}", config.getString("test.interpol"));
210     }
211 
212     /**
213      * Tests an interpolation over multiple levels (i.e. the replacement of a variable is another variable and so on).
214      *
215      * @param config the configuration to test
216      */
217     public static void testMultipleInterpolation(final Configuration config) {
218         config.setProperty("test.base-level", "/base-level");
219         config.setProperty("test.first-level", "${test.base-level}/first-level");
220         config.setProperty("test.second-level", "${test.first-level}/second-level");
221         config.setProperty("test.third-level", "${test.second-level}/third-level");
222 
223         final String expectedValue = "/base-level/first-level/second-level/third-level";
224 
225         assertEquals(expectedValue, config.getString("test.third-level"));
226     }
227 
228     private InterpolationTestHelper() {
229         // empty
230     }
231 }