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  
18  package org.apache.commons.text;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  
22  import java.net.InetAddress;
23  import java.net.UnknownHostException;
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  import org.apache.commons.text.lookup.DefaultStringLookup;
28  import org.apache.commons.text.lookup.StringLookup;
29  import org.apache.commons.text.lookup.StringLookupFactory;
30  import org.junit.jupiter.api.Assertions;
31  import org.junit.jupiter.api.Test;
32  
33  class StringSubstitutorWithInterpolatorStringLookupTest {
34  
35      private static StringLookup createInterpolatorWithLookups(final DefaultStringLookup... lookups) {
36          final Map<String, StringLookup> lookupMap = new HashMap<>();
37          for (final DefaultStringLookup lookup : lookups) {
38              lookupMap.put(lookup.getKey().toLowerCase(), lookup.getStringLookup());
39          }
40  
41          return StringLookupFactory.INSTANCE.interpolatorStringLookup(lookupMap, null, false);
42      }
43  
44      @Test
45      void testCustomFunctionWithDefaults() {
46          testCustomFunctionWithDefaults(true);
47      }
48  
49      private void testCustomFunctionWithDefaults(final boolean addDefaultLookups) {
50          final String key = "key";
51          final String value = "value";
52          final Map<String, String> map = new HashMap<>();
53          map.put(key, value);
54          final StringLookup mapStringLookup = StringLookupFactory.INSTANCE.functionStringLookup(map::get);
55          final Map<String, StringLookup> stringLookupMap = new HashMap<>();
56          stringLookupMap.put("customLookup", mapStringLookup);
57          final StringSubstitutor strSubst = new StringSubstitutor(
58              StringLookupFactory.INSTANCE.interpolatorStringLookup(stringLookupMap, null, addDefaultLookups));
59          if (addDefaultLookups) {
60              final String spKey = "user.name";
61              Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
62          }
63          Assertions.assertEquals("value", strSubst.replace("${customLookup:key}"));
64      }
65  
66      @Test
67      void testCustomFunctionWithoutDefaults() {
68          testCustomFunctionWithDefaults(false);
69      }
70  
71      @Test
72      void testCustomMapWithDefaults() {
73          testCustomMapWithDefaults(true);
74      }
75  
76      private void testCustomMapWithDefaults(final boolean addDefaultLookups) {
77          final String key = "key";
78          final String value = "value";
79          final Map<String, String> map = new HashMap<>();
80          map.put(key, value);
81          final StringLookup mapStringLookup = StringLookupFactory.INSTANCE.mapStringLookup(map);
82          final Map<String, StringLookup> stringLookupMap = new HashMap<>();
83          stringLookupMap.put("customLookup", mapStringLookup);
84          final StringSubstitutor strSubst = new StringSubstitutor(
85              StringLookupFactory.INSTANCE.interpolatorStringLookup(stringLookupMap, null, addDefaultLookups));
86          if (addDefaultLookups) {
87              final String spKey = "user.name";
88              Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
89          }
90          Assertions.assertEquals("value", strSubst.replace("${customLookup:key}"));
91          Assertions.assertEquals("${UnknownLookup:key}", strSubst.replace("${UnknownLookup:key}"));
92      }
93  
94      @Test
95      void testCustomMapWithoutDefaults() {
96          testCustomMapWithDefaults(false);
97      }
98      @Test
99      void testDefaultInterpolator() {
100         // Used to cut and paste into the docs.
101         // @formatter:off
102         final StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
103         final String text = interpolator.replace(
104                 "Base64 Decoder:        ${base64Decoder:SGVsbG9Xb3JsZCE=}\n"
105               + "Base64 Encoder:        ${base64Encoder:HelloWorld!}\n"
106               + "Java Constant:         ${const:java.awt.event.KeyEvent.VK_ESCAPE}\n"
107               + "Date:                  ${date:yyyy-MM-dd}\n"
108               + "Environment Variable:  ${env:USERNAME}\n"
109               + "File Content:          ${file:UTF-8:src/test/resources/org/apache/commons/text/document.properties}\n"
110               + "Java:                  ${java:version}\n"
111               + "Localhost:             ${localhost:canonical-name}\n"
112               + "Properties File:       ${properties:src/test/resources/org/apache/commons/text/document.properties::mykey}\n"
113               + "Resource Bundle:       ${resourceBundle:org.apache.commons.text.example.testResourceBundleLookup:mykey}\n"
114               + "System Property:       ${sys:user.dir}\n"
115               + "URL Decoder:           ${urlDecoder:Hello%20World%21}\n"
116               + "URL Encoder:           ${urlEncoder:Hello World!}\n"
117               + "XML XPath:             ${xml:src/test/resources/org/apache/commons/text/document.xml:/root/path/to/node}\n"
118         );
119         // @formatter:on
120         Assertions.assertNotNull(text);
121         // TEXT-171:
122         Assertions.assertFalse(text.contains("${base64Decoder:SGVsbG9Xb3JsZCE=}"));
123         Assertions.assertFalse(text.contains("${base64Encoder:HelloWorld!}"));
124         Assertions.assertFalse(text.contains("${urlDecoder:Hello%20World%21}"));
125         Assertions.assertFalse(text.contains("${urlEncoder:Hello World!}"));
126         Assertions.assertFalse(text.contains("${resourceBundle:org.apache.commons.text.example.testResourceBundleLookup:mykey}"));
127     }
128 
129     @Test
130     void testDefaultValueForMissingKeyInResourceBundle() {
131         final StringLookup interpolatorStringLookup = StringLookupFactory.INSTANCE.interpolatorStringLookup(
132             StringLookupFactory.INSTANCE.resourceBundleStringLookup("org.apache.commons.text.example.testResourceBundleLookup"));
133         assertEquals("${missingKey:-defaultValue}", interpolatorStringLookup.apply("keyWithMissingKey"));
134         assertEquals("${missingKey:-defaultValue}", interpolatorStringLookup.lookup("keyWithMissingKey"));
135         final StringSubstitutor stringSubstitutor = new StringSubstitutor(interpolatorStringLookup);
136         // The following would throw a MissingResourceException before TEXT-165.
137         assertEquals("defaultValue", stringSubstitutor.replace("${keyWithMissingKey}"));
138     }
139 
140     @Test
141     void testDnsLookup() throws UnknownHostException {
142         final StringSubstitutor strSubst =
143                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.DNS));
144         final String hostName = InetAddress.getLocalHost().getHostName();
145         Assertions.assertEquals(InetAddress.getByName(hostName).getHostAddress(),
146             strSubst.replace("${dns:" + hostName + "}"));
147     }
148 
149     @Test
150     void testDnsLookup_disabledByDefault() throws UnknownHostException {
151         final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
152         final String hostName = InetAddress.getLocalHost().getHostName();
153         final String input = "${dns:" + hostName + "}";
154         Assertions.assertEquals(input, strSubst.replace(input));
155     }
156 
157     @Test
158     void testDnsLookupAddress() throws UnknownHostException {
159         final StringSubstitutor strSubst =
160                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.DNS));
161         Assertions.assertEquals(InetAddress.getByName("apache.org").getHostAddress(),
162             strSubst.replace("${dns:address|apache.org}"));
163     }
164 
165     @Test
166     void testDnsLookupCanonicalName() throws UnknownHostException {
167         final StringSubstitutor strSubst =
168                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.DNS));
169         final String address = InetAddress.getLocalHost().getHostAddress();
170         final InetAddress inetAddress = InetAddress.getByName(address);
171         Assertions.assertEquals(inetAddress.getCanonicalHostName(),
172             strSubst.replace("${dns:canonical-name|" + address + "}"));
173     }
174 
175     @Test
176     void testDnsLookupName() throws UnknownHostException {
177         final StringSubstitutor strSubst =
178                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.DNS));
179         final String address = InetAddress.getLocalHost().getHostAddress();
180         final InetAddress inetAddress = InetAddress.getByName(address);
181         Assertions.assertEquals(inetAddress.getHostName(), strSubst.replace("${dns:name|" + address + "}"));
182     }
183 
184     @Test
185     void testDnsLookupNameUntrimmed() throws UnknownHostException {
186         final StringSubstitutor strSubst =
187                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.DNS));
188         final String address = InetAddress.getLocalHost().getHostAddress();
189         final InetAddress inetAddress = InetAddress.getByName(address);
190         Assertions.assertEquals(inetAddress.getHostName(), strSubst.replace("${dns:name| " + address + " }"));
191     }
192 
193     @Test
194     void testDnsLookupUnknown() {
195         final StringSubstitutor strSubst =
196                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.DNS));
197         final String unknown = "${dns: u n k n o w n}";
198         Assertions.assertEquals(unknown, strSubst.replace(unknown));
199     }
200 
201     @Test
202     void testJavaScript() {
203         final StringSubstitutor strSubst =
204                 new StringSubstitutor(createInterpolatorWithLookups(DefaultStringLookup.SCRIPT));
205 
206         Assertions.assertEquals("Hello World!", strSubst.replace("${script:javascript:\"Hello World!\"}"));
207         Assertions.assertEquals("7", strSubst.replace("${script:javascript:3 + 4}"));
208     }
209 
210     @Test
211     void testJavaScript_disabledByDefault() {
212         final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
213 
214         Assertions.assertEquals("${script:javascript:3 + 4}", strSubst.replace("${script:javascript:3 + 4}"));
215     }
216 
217     @Test
218     void testLocalHostLookup_Address() throws UnknownHostException {
219         final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
220         Assertions.assertEquals(InetAddress.getLocalHost().getHostAddress(), strSubst.replace("${localhost:address}"));
221     }
222 
223     @Test
224     void testLocalHostLookup_CanonicalName() throws UnknownHostException {
225         final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
226         Assertions.assertEquals(InetAddress.getLocalHost().getCanonicalHostName(),
227             strSubst.replace("${localhost:canonical-name}"));
228     }
229 
230     @Test
231     void testLocalHostLookup_Name() throws UnknownHostException {
232         final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
233         Assertions.assertEquals(InetAddress.getLocalHost().getHostName(), strSubst.replace("${localhost:name}"));
234     }
235 
236     @Test
237     void testMapAndSystemProperty() {
238         final String key = "key";
239         final String value = "value";
240         final Map<String, String> map = new HashMap<>();
241         map.put(key, value);
242         final StringSubstitutor strSubst = new StringSubstitutor(
243             StringLookupFactory.INSTANCE.interpolatorStringLookup(map));
244         final String spKey = "user.name";
245         Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
246         Assertions.assertEquals(value, strSubst.replace("${" + key + "}"));
247     }
248 
249     @Test
250     void testSystemProperty() {
251         final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
252         final String spKey = "user.name";
253         Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
254     }
255 
256     @Test
257     void testSystemPropertyDefaultStringLookup() {
258         final StringSubstitutor strSubst = new StringSubstitutor(
259             StringLookupFactory.INSTANCE.interpolatorStringLookup(StringLookupFactory.INSTANCE.systemPropertyStringLookup()));
260         final String spKey = "user.name";
261         Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${" + spKey + "}"));
262         Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
263     }
264 }