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.text.lookup;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertSame;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Locale;
28  import java.util.Map;
29  import java.util.Properties;
30  import java.util.Set;
31  
32  import javax.xml.XMLConstants;
33  
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Tests {@link StringLookupFactory}.
38   */
39  class StringLookupFactoryTest {
40  
41      public static void assertDefaultKeys(final Map<String, StringLookup> stringLookupMap) {
42          // included
43          assertMappedLookups(stringLookupMap,
44                  "base64",
45                  StringLookupFactory.KEY_BASE64_DECODER,
46                  StringLookupFactory.KEY_BASE64_ENCODER,
47                  StringLookupFactory.KEY_CONST,
48                  StringLookupFactory.KEY_DATE,
49                  StringLookupFactory.KEY_ENV,
50                  StringLookupFactory.KEY_FILE,
51                  StringLookupFactory.KEY_JAVA,
52                  StringLookupFactory.KEY_LOCALHOST,
53                  StringLookupFactory.KEY_LOOPBACK_ADDRESS,
54                  StringLookupFactory.KEY_PROPERTIES,
55                  StringLookupFactory.KEY_RESOURCE_BUNDLE,
56                  StringLookupFactory.KEY_SYS,
57                  StringLookupFactory.KEY_URL_DECODER,
58                  StringLookupFactory.KEY_URL_ENCODER,
59                  StringLookupFactory.KEY_XML,
60                  StringLookupFactory.KEY_XML_DECODER,
61                  StringLookupFactory.KEY_XML_ENCODER);
62      }
63  
64      private static void assertMappedLookups(final Map<String, StringLookup> lookupMap, final String... keys) {
65          final Set<String> remainingKeys = new HashSet<>(lookupMap.keySet());
66  
67          for (final String key : keys) {
68              final String normalizedKey = StringLookupFactory.toKey(key);
69              assertNotNull(normalizedKey, () -> "Expected map to contain string lookup for key " + key);
70  
71              remainingKeys.remove(normalizedKey);
72          }
73  
74          assertTrue(remainingKeys.isEmpty(), () -> "Unexpected keys in lookup map: " + remainingKeys);
75      }
76  
77      private static void checkDefaultStringLookupsHolder(final Properties props, final String... keys) {
78          final StringLookupFactory.DefaultStringLookupsHolder holder =
79                  new StringLookupFactory.DefaultStringLookupsHolder(props);
80  
81          final Map<String, StringLookup> lookupMap = holder.getDefaultStringLookups();
82  
83          assertMappedLookups(lookupMap, keys);
84      }
85  
86      /**
87       * Main method used to verify the default string lookups resolved during JVM execution.
88       * @param args
89       */
90      public static void main(final String[] args) {
91          final Map<String, StringLookup> lookupMap = new HashMap<>();
92          StringLookupFactory.INSTANCE.addDefaultStringLookups(lookupMap);
93  
94          System.out.println("Default string lookups");
95          for (final String key : lookupMap.keySet()) {
96              System.out.println("- " + key);
97          }
98      }
99  
100     @Test
101     void testAddDefaultStringLookupsMap() {
102         final Map<String, StringLookup> stringLookupMap = new HashMap<>();
103         StringLookupFactory.INSTANCE.addDefaultStringLookups(stringLookupMap);
104         assertDefaultKeys(stringLookupMap);
105     }
106 
107     @Test
108     void testAddDefaultStringLookupsNull() {
109         StringLookupFactory.INSTANCE.addDefaultStringLookups(null);
110     }
111 
112     /**
113      * Tests that we return the singleton.
114      */
115     @Test
116     void testDefault() {
117         final StringLookupFactory stringLookupFactory = StringLookupFactory.INSTANCE;
118         final Map<String, StringLookup> stringLookupMap = new HashMap<>();
119         stringLookupFactory.addDefaultStringLookups(stringLookupMap);
120         assertTrue(stringLookupMap.containsKey("base64"));
121         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_BASE64_ENCODER.toLowerCase(Locale.ROOT)));
122         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_CONST.toLowerCase(Locale.ROOT)));
123         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_DATE));
124         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_ENV.toLowerCase(Locale.ROOT)));
125         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_FILE.toLowerCase(Locale.ROOT)));
126         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_JAVA.toLowerCase(Locale.ROOT)));
127         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_LOCALHOST.toLowerCase(Locale.ROOT)));
128         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_LOOPBACK_ADDRESS.toLowerCase(Locale.ROOT)));
129         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_PROPERTIES.toLowerCase(Locale.ROOT)));
130         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_RESOURCE_BUNDLE.toLowerCase(Locale.ROOT)));
131         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_SYS.toLowerCase(Locale.ROOT)));
132         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_URL_DECODER.toLowerCase(Locale.ROOT)));
133         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_URL_ENCODER.toLowerCase(Locale.ROOT)));
134         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_XML.toLowerCase(Locale.ROOT)));
135         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_XML_DECODER.toLowerCase(Locale.ROOT)));
136         assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_XML_ENCODER.toLowerCase(Locale.ROOT)));
137     }
138 
139     @Test
140     void testDefaultStringLookupsHolder_allLookups() {
141         final Properties props = new Properties();
142         props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY,
143                 "BASE64_DECODER BASE64_ENCODER const, date, dns, environment "
144                 + "file ,java, local_host properties, resource_bundle,script,system_properties "
145                 + "url url_decoder  , url_encoder, xml");
146 
147         checkDefaultStringLookupsHolder(props,
148                 "base64",
149                 StringLookupFactory.KEY_BASE64_DECODER,
150                 StringLookupFactory.KEY_BASE64_ENCODER,
151                 StringLookupFactory.KEY_CONST,
152                 StringLookupFactory.KEY_DATE,
153                 StringLookupFactory.KEY_ENV,
154                 StringLookupFactory.KEY_FILE,
155                 StringLookupFactory.KEY_JAVA,
156                 StringLookupFactory.KEY_LOCALHOST,
157                 StringLookupFactory.KEY_LOOPBACK_ADDRESS,
158                 StringLookupFactory.KEY_PROPERTIES,
159                 StringLookupFactory.KEY_RESOURCE_BUNDLE,
160                 StringLookupFactory.KEY_SYS,
161                 StringLookupFactory.KEY_URL_DECODER,
162                 StringLookupFactory.KEY_URL_ENCODER,
163                 StringLookupFactory.KEY_XML,
164 
165                 StringLookupFactory.KEY_DNS,
166                 StringLookupFactory.KEY_URL,
167                 StringLookupFactory.KEY_SCRIPT);
168     }
169 
170     @Test
171     void testDefaultStringLookupsHolder_givenSingleLookup() {
172         final Properties props = new Properties();
173         props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "base64_encoder");
174 
175         checkDefaultStringLookupsHolder(props,
176                 "base64",
177                 StringLookupFactory.KEY_BASE64_ENCODER);
178     }
179 
180     @Test
181     void testDefaultStringLookupsHolder_givenSingleLookup_weirdString() {
182         final Properties props = new Properties();
183         props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, " \n \t  ,, DnS , , ");
184 
185         checkDefaultStringLookupsHolder(props, StringLookupFactory.KEY_DNS);
186     }
187 
188     @Test
189     void testDefaultStringLookupsHolder_invalidLookupsDefinition() {
190         final Properties props = new Properties();
191         props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "base64_encoder nope");
192 
193         final Exception exc = assertThrows(IllegalArgumentException.class,
194                 () -> new StringLookupFactory.DefaultStringLookupsHolder(props));
195         assertEquals("Invalid default string lookups definition: base64_encoder nope", exc.getMessage());
196     }
197 
198     @Test
199     void testDefaultStringLookupsHolder_lookupsPropertyEmptyAndBlank() {
200         final Properties propsWithNull = new Properties();
201         propsWithNull.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "");
202 
203         checkDefaultStringLookupsHolder(propsWithNull);
204 
205         final Properties propsWithBlank = new Properties();
206         propsWithBlank.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, " ");
207 
208         checkDefaultStringLookupsHolder(propsWithBlank);
209     }
210 
211     @Test
212     void testDefaultStringLookupsHolder_lookupsPropertyNotPresent() {
213         checkDefaultStringLookupsHolder(new Properties(),
214                 "base64",
215                 StringLookupFactory.KEY_BASE64_DECODER,
216                 StringLookupFactory.KEY_BASE64_ENCODER,
217                 StringLookupFactory.KEY_CONST,
218                 StringLookupFactory.KEY_DATE,
219                 StringLookupFactory.KEY_ENV,
220                 StringLookupFactory.KEY_FILE,
221                 StringLookupFactory.KEY_JAVA,
222                 StringLookupFactory.KEY_LOCALHOST,
223                 StringLookupFactory.KEY_LOOPBACK_ADDRESS,
224                 StringLookupFactory.KEY_PROPERTIES,
225                 StringLookupFactory.KEY_RESOURCE_BUNDLE,
226                 StringLookupFactory.KEY_SYS,
227                 StringLookupFactory.KEY_URL_DECODER,
228                 StringLookupFactory.KEY_URL_ENCODER,
229                 StringLookupFactory.KEY_XML,
230                 StringLookupFactory.KEY_XML_DECODER,
231                 StringLookupFactory.KEY_XML_ENCODER);
232     }
233 
234     @Test
235     void testDefaultStringLookupsHolder_multipleLookups() {
236         final Properties props = new Properties();
237         props.setProperty(StringLookupFactory.DEFAULT_STRING_LOOKUPS_PROPERTY, "dns, url script ");
238 
239         checkDefaultStringLookupsHolder(props,
240                 StringLookupFactory.KEY_DNS,
241                 StringLookupFactory.KEY_URL,
242                 StringLookupFactory.KEY_SCRIPT);
243     }
244 
245     /**
246      * Tests that we return the singleton.
247      */
248     @Test
249     void testSingletons() {
250         final StringLookupFactory stringLookupFactory = StringLookupFactory.INSTANCE;
251         assertSame(StringLookupFactory.INSTANCE_BASE64_DECODER,
252             stringLookupFactory.base64DecoderStringLookup());
253         assertSame(StringLookupFactory.INSTANCE_BASE64_ENCODER,
254             stringLookupFactory.base64EncoderStringLookup());
255         assertSame(ConstantStringLookup.INSTANCE, stringLookupFactory.constantStringLookup());
256         assertSame(DateStringLookup.INSTANCE, stringLookupFactory.dateStringLookup());
257         assertSame(DnsStringLookup.INSTANCE, stringLookupFactory.dnsStringLookup());
258         assertSame(StringLookupFactory.INSTANCE_ENVIRONMENT_VARIABLES,
259             stringLookupFactory.environmentVariableStringLookup());
260         assertSame(InterpolatorStringLookup.INSTANCE, stringLookupFactory.interpolatorStringLookup());
261         assertSame(JavaPlatformStringLookup.INSTANCE, stringLookupFactory.javaPlatformStringLookup());
262         assertSame(InetAddressStringLookup.LOCAL_HOST, stringLookupFactory.localHostStringLookup());
263         assertSame(InetAddressStringLookup.LOOPACK_ADDRESS, stringLookupFactory.loopbackAddressStringLookup());
264         assertSame(StringLookupFactory.INSTANCE_NULL, stringLookupFactory.nullStringLookup());
265         assertSame(ResourceBundleStringLookup.INSTANCE, stringLookupFactory.resourceBundleStringLookup());
266         assertSame(ScriptStringLookup.INSTANCE, stringLookupFactory.scriptStringLookup());
267         assertSame(StringLookupFactory.INSTANCE_SYSTEM_PROPERTIES,
268             stringLookupFactory.systemPropertyStringLookup());
269         assertSame(UrlDecoderStringLookup.INSTANCE, stringLookupFactory.urlDecoderStringLookup());
270         assertSame(UrlEncoderStringLookup.INSTANCE, stringLookupFactory.urlEncoderStringLookup());
271         assertSame(UrlStringLookup.INSTANCE, stringLookupFactory.urlStringLookup());
272         assertSame(XmlStringLookup.INSTANCE, stringLookupFactory.xmlStringLookup());
273         assertSame(XmlDecoderStringLookup.INSTANCE, stringLookupFactory.xmlDecoderStringLookup());
274         assertSame(XmlEncoderStringLookup.INSTANCE, stringLookupFactory.xmlEncoderStringLookup());
275     }
276 
277     @Test
278     void testXmlStringLookup() {
279         final StringLookupFactory stringLookupFactory = StringLookupFactory.INSTANCE;
280         final HashMap<String, Boolean> features = new HashMap<>(1);
281         features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
282         XmlStringLookupTest.assertLookup(stringLookupFactory.xmlStringLookup(features));
283         XmlStringLookupTest.assertLookup(stringLookupFactory.xmlStringLookup(new HashMap<>()));
284     }
285 }