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    *     http://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  
31  /**
32   * A helper class that defines a bunch of tests related to variable interpolation. It can be used for running these
33   * tests on different configuration implementations.
34   */
35  public class InterpolationTestHelper {
36      /**
37       * Tests accessing and manipulating the interpolator object.
38       *
39       * @param config the configuration to test
40       */
41      public static void testGetInterpolator(final AbstractConfiguration config) {
42          config.addProperty("var", "${echo:testVar}");
43          final ConfigurationInterpolator interpol = config.getInterpolator();
44          interpol.registerLookup("echo", varName -> "Value of variable " + varName);
45          assertEquals("Value of variable testVar", config.getString("var"));
46      }
47  
48      /**
49       * Tests obtaining a configuration with all variables replaced by their actual values.
50       *
51       * @param config the configuration to test
52       * @return the interpolated configuration
53       */
54      public static Configuration testInterpolatedConfiguration(final AbstractConfiguration config) {
55          config.setProperty("applicationRoot", "/home/applicationRoot");
56          config.setProperty("db", "${applicationRoot}/db/hypersonic");
57          config.setProperty("inttest.interpol", "${unknown.property}");
58          config.setProperty("intkey.code", "${const:java.awt.event.KeyEvent.VK_CANCEL}");
59          config.setProperty("inttest.sysprop", "${sys:java.version}");
60          config.setProperty("inttest.numvalue", "3\\,1415");
61          config.setProperty("inttest.value", "${inttest.numvalue}");
62          config.setProperty("inttest.list", "${db}");
63          config.addProperty("inttest.list", "${inttest.value}");
64  
65          final Configuration c = config.interpolatedConfiguration();
66          assertEquals("/home/applicationRoot/db/hypersonic", c.getProperty("db"));
67          assertEquals(KeyEvent.VK_CANCEL, c.getInt("intkey.code"));
68          assertEquals(System.getProperty("java.version"), c.getProperty("inttest.sysprop"));
69          assertEquals("3,1415", c.getProperty("inttest.value"));
70          final List<?> lst = (List<?>) c.getProperty("inttest.list");
71          assertEquals(Arrays.asList("/home/applicationRoot/db/hypersonic", "3,1415"), lst);
72          assertEquals("${unknown.property}", c.getProperty("inttest.interpol"));
73  
74          return c;
75      }
76  
77      /**
78       * Tests basic interpolation facilities of the specified configuration.
79       *
80       * @param config the configuration to test
81       */
82      public static void testInterpolation(final Configuration config) {
83          config.setProperty("applicationRoot", "/home/applicationRoot");
84          config.setProperty("db", "${applicationRoot}/db/hypersonic");
85          final String unInterpolatedValue = "${applicationRoot2}/db/hypersonic";
86          config.setProperty("dbFailedInterpolate", unInterpolatedValue);
87          final String dbProp = "/home/applicationRoot/db/hypersonic";
88  
89          assertEquals(dbProp, config.getString("db"));
90          assertEquals(unInterpolatedValue, config.getString("dbFailedInterpolate"));
91  
92          config.setProperty("arrayInt", "${applicationRoot}/1");
93          final String[] arrayInt = config.getStringArray("arrayInt");
94          assertEquals("/home/applicationRoot/1", arrayInt[0]);
95  
96          config.addProperty("path", Arrays.asList("/temp", "C:\\Temp", "/usr/local/tmp"));
97          config.setProperty("path.current", "${path}");
98          assertEquals("/temp", config.getString("path.current"));
99      }
100 
101     /**
102      * Tests interpolation of constant values.
103      *
104      * @param config the configuration to test
105      */
106     public static void testInterpolationConstants(final Configuration config) {
107         config.addProperty("key.code", "${const:java.awt.event.KeyEvent.VK_CANCEL}");
108         assertEquals(KeyEvent.VK_CANCEL, config.getInt("key.code"));
109         assertEquals(KeyEvent.VK_CANCEL, config.getInt("key.code"));
110     }
111 
112     /**
113      * Tests interpolation of environment properties.
114      *
115      * @param config the configuration to test
116      */
117     public static void testInterpolationEnvironment(final Configuration config) {
118         final Map<String, String> env = System.getenv();
119         for (final Map.Entry<String, String> e : env.entrySet()) {
120             config.addProperty("prop" + e.getKey(), "${env:" + e.getKey() + "}");
121         }
122 
123         for (final Map.Entry<String, String> e : env.entrySet()) {
124             assertEquals(e.getValue(), config.getString("prop" + e.getKey()), "Wrong value for environment property " + e.getKey());
125         }
126     }
127 
128     /**
129      * Tests whether a variable can be escaped, so that it won't be interpolated.
130      *
131      * @param config the configuration to test
132      */
133     public static void testInterpolationEscaped(final Configuration config) {
134         config.addProperty("var", "x");
135         config.addProperty("escVar", "Use the variable $${${var}}.");
136         assertEquals("Use the variable ${x}.", config.getString("escVar"));
137     }
138 
139     /**
140      * Tests interpolation of localhost properties.
141      *
142      * @param config the configuration to test
143      */
144     public static void testInterpolationLocalhost(final Configuration config) {
145         final String[] localhostKeys = {"name", "canonical-name", "address"};
146         final InetAddress localHost = assertDoesNotThrow(InetAddress::getLocalHost);
147         final String[] localhostValues = {localHost.getHostName(), localHost.getCanonicalHostName(), localHost.getHostAddress()};
148         for (int i = 0; i < localhostKeys.length; i++) {
149             config.addProperty("prop" + i, "${localhost:" + localhostKeys[i] + "}");
150         }
151 
152         for (int i = 0; i < localhostKeys.length; i++) {
153             assertEquals(localhostValues[i], config.getString("prop" + i), "Wrong value for system property " + localhostKeys[i]);
154         }
155     }
156 
157     /**
158      * Tests an invalid interpolation that results in an infinite loop. This loop should be detected and an exception should
159      * be thrown.
160      *
161      * @param config the configuration to test
162      */
163     public static void testInterpolationLoop(final Configuration config) {
164         config.setProperty("test.a", "${test.b}");
165         config.setProperty("test.b", "${test.a}");
166 
167         assertThrows(IllegalStateException.class, () -> config.getString("test.a"));
168     }
169 
170     /**
171      * Tests interpolation when a subset configuration is involved.
172      *
173      * @param config the configuration to test
174      */
175     public static void testInterpolationSubset(final Configuration config) {
176         config.addProperty("test.a", Integer.valueOf(42));
177         config.addProperty("test.b", "${test.a}");
178         assertEquals(42, config.getInt("test.b"));
179         final Configuration subset = config.subset("test");
180         assertEquals("42", subset.getString("b"));
181         assertEquals(42, subset.getInt("b"));
182     }
183 
184     /**
185      * Tests interpolation of system properties.
186      *
187      * @param config the configuration to test
188      */
189     public static void testInterpolationSystemProperties(final Configuration config) {
190         final String[] sysProperties = {"java.version", "java.vendor", "os.name", "java.class.path"};
191         for (int i = 0; i < sysProperties.length; i++) {
192             config.addProperty("prop" + i, "${sys:" + sysProperties[i] + "}");
193         }
194 
195         for (int i = 0; i < sysProperties.length; i++) {
196             assertEquals(System.getProperty(sysProperties[i]), config.getString("prop" + i), "Wrong value for system property " + sysProperties[i]);
197         }
198     }
199 
200     /**
201      * Tests interpolation when the referred property is not found.
202      *
203      * @param config the configuration to test
204      */
205     public static void testInterpolationUnknownProperty(final Configuration config) {
206         config.addProperty("test.interpol", "${unknown.property}");
207         assertEquals("${unknown.property}", config.getString("test.interpol"));
208     }
209 
210     /**
211      * Tests an interpolation over multiple levels (i.e. the replacement of a variable is another variable and so on).
212      *
213      * @param config the configuration to test
214      */
215     public static void testMultipleInterpolation(final Configuration config) {
216         config.setProperty("test.base-level", "/base-level");
217         config.setProperty("test.first-level", "${test.base-level}/first-level");
218         config.setProperty("test.second-level", "${test.first-level}/second-level");
219         config.setProperty("test.third-level", "${test.second-level}/third-level");
220 
221         final String expectedValue = "/base-level/first-level/second-level/third-level";
222 
223         assertEquals(expectedValue, config.getString("test.third-level"));
224     }
225 }