Skip to content

Commit

Permalink
Make default string lookups configurable via system property. Remove …
Browse files Browse the repository at this point in the history
…dns, url, and script lookups from defaults. (#341)

Co-authored-by: Gary Gregory <garydgregory@users.noreply.github.com>
  • Loading branch information
darkma773r and garydgregory committed Sep 23, 2022
1 parent 1c03406 commit b9b40b9
Show file tree
Hide file tree
Showing 10 changed files with 580 additions and 250 deletions.
3 changes: 1 addition & 2 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,14 @@ The <action> type attribute can be add,update,fix,remove.
<action issue="TEXT-209" type="fix" dev="ggregory" due-to="Arturo Bernal">Use Math.min() call instead of doing it manually. #335.</action>
<action type="fix" dev="ggregory" due-to="ValentijnvdBeek, Gary Gregory">TextStringBuilder: Throw OutOfMemoryError instead of NegativeArraySizeException.</action>
<action type="fix" dev="ggregory" due-to="ValentijnvdBeek, Gary Gregory">TextStringBuilder: Can't grow to sizes up to Integer.MAX_VALUE.</action>
<action type="fix" dev="mattjuntunen">Make default string lookups configurable via system property. Remove dns, url, and script lookups from defaults. If these lookups are required for use in StringSubstitutor.createInterpolator(), they must be enabled via system property. See StringLookupFactory for details.</action>
<!-- ADD -->
<action issue="TEXT-207" type="add" dev="mattjuntunen">Add DoubleFormat utility.</action>
<action issue="TEXT-190" type="add" dev="kinow" due-to="Benjamin Bing">Document negative limit for WordUtils abbreviate method</action>
<action issue="TEXT-188" type="add" dev="kinow" due-to="Jakob Vesterstrøm">Speed up LevenshteinDistance with threshold by exiting early</action>
<action issue="TEXT-185" type="add" dev="ggregory" due-to="Larry West, Gary Gregory">Release Notes page hasn't been updated for 1.9 release yet.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add StrBuilder.isNotEmpty().</action>
<!-- UPDATE -->
<action type="update" dev="kinow" due-to="Dependabot">Bump actions/cache from v2 to v3.0.8 #205, #217, #234, #339.</action>
<action type="update" dev="kinow" due-to="Dependabot, Gary Gregory">Bump actions/checkout from 1 to 3.0.2 #138, #146, #165, #183, #274, #279, #304.</action>
<action type="update" dev="kinow" due-to="Dependabot">Bump actions/setup-java from v1.4.0 to 3 #147, #156, #155, #172, #215, #314.</action>
<action type="update" dev="kinow" due-to="Dependabot">Bump github/codeql-action from 1 to 2 #319.</action>
<action type="update" dev="ggregory" due-to="Dependabot">Bump checkstyle from 8.34 to 9.3, #141, #168, #182, #188, #193, #201, #208, #211, #228, #235, #245, #253, #255, #262, #270, #280, #287, #299, #315, #321.</action>
Expand Down
94 changes: 84 additions & 10 deletions src/main/java/org/apache/commons/text/StringSubstitutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,26 +141,28 @@
*
* <pre>
* final StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
* interpolator.setEnableSubstitutionInVariables(true); // Allows for nested $'s.
* final String text = interpolator.replace("Base64 Decoder: ${base64Decoder:SGVsbG9Xb3JsZCE=}\n"
* final String text = interpolator.replace(
* "Base64 Decoder: ${base64Decoder:SGVsbG9Xb3JsZCE=}\n"
* + "Base64 Encoder: ${base64Encoder:HelloWorld!}\n"
* + "Java Constant: ${const:java.awt.event.KeyEvent.VK_ESCAPE}\n"
* + "Date: ${date:yyyy-MM-dd}\n" + "DNS: ${dns:address|apache.org}\n"
* + "Date: ${date:yyyy-MM-dd}\n"
* + "Environment Variable: ${env:USERNAME}\n"
* + "File Content: ${file:UTF-8:src/test/resources/document.properties}\n"
* + "Java: ${java:version}\n" + "Localhost: ${localhost:canonical-name}\n"
* + "Java: ${java:version}\n"
* + "Localhost: ${localhost:canonical-name}\n"
* + "Properties File: ${properties:src/test/resources/document.properties::mykey}\n"
* + "Resource Bundle: ${resourceBundle:org.apache.commons.text.example.testResourceBundleLookup:mykey}\n"
* + "Script: ${script:javascript:3 + 4}\n" + "System Property: ${sys:user.dir}\n"
* + "System Property: ${sys:user.dir}\n"
* + "URL Decoder: ${urlDecoder:Hello%20World%21}\n"
* + "URL Encoder: ${urlEncoder:Hello World!}\n"
* + "URL Content (HTTP): ${url:UTF-8:http://www.apache.org}\n"
* + "URL Content (HTTPS): ${url:UTF-8:https://www.apache.org}\n"
* + "URL Content (File): ${url:UTF-8:file:///${sys:user.dir}/src/test/resources/document.properties}\n"
* + "XML XPath: ${xml:src/test/resources/document.xml:/root/path/to/node}\n");
* </pre>
* <p>
* For documentation of each lookup, see {@link StringLookupFactory}.
* For documentation and a full list of available lookups, see {@link StringLookupFactory}.
* </p>
* <p><strong>NOTE:</strong> The list of lookups available by default in {@link #createInterpolator()} changed
* in version {@code 1.10.0}. See the {@link StringLookupFactory} documentation for details and an explanation
* on how to reproduce the previous functionality.
* </p>
*
* <h2>Using Recursive Variable Replacement</h2>
Expand Down Expand Up @@ -292,9 +294,81 @@ public String toString() {
*
* <pre>
* StringSubstitutor.createInterpolator().replace(
* "OS name: ${sys:os.name}, " + "3 + 4 = ${script:javascript:3 + 4}");
* "OS name: ${sys:os.name}, user: ${env:USER}");
* </pre>
*
* <p>The table below lists the lookups available by default in the returned instance. These
* may be modified through the use of the {@value StringLookupFactory#DEFAULT_STRING_LOOKUPS_PROPERTY}
* system property, as described in the {@link StringLookupFactory} documentation.</p>
*
* <p><strong>NOTE:</strong> The list of lookups available by default changed in version {@code 1.10.0}.
* Configuration via system property (as mentioned above) may be necessary to reproduce previous functionality.
* </p>
*
* <table>
* <caption>Default Lookups</caption>
* <tr>
* <th>Key</th>
* <th>Lookup</th>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_BASE64_DECODER}</td>
* <td>{@link StringLookupFactory#base64DecoderStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_BASE64_ENCODER}</td>
* <td>{@link StringLookupFactory#base64EncoderStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_CONST}</td>
* <td>{@link StringLookupFactory#constantStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_DATE}</td>
* <td>{@link StringLookupFactory#dateStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_ENV}</td>
* <td>{@link StringLookupFactory#environmentVariableStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_FILE}</td>
* <td>{@link StringLookupFactory#fileStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_JAVA}</td>
* <td>{@link StringLookupFactory#javaPlatformStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_LOCALHOST}</td>
* <td>{@link StringLookupFactory#localHostStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_PROPERTIES}</td>
* <td>{@link StringLookupFactory#propertiesStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_RESOURCE_BUNDLE}</td>
* <td>{@link StringLookupFactory#resourceBundleStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_SYS}</td>
* <td>{@link StringLookupFactory#systemPropertyStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_URL_DECODER}</td>
* <td>{@link StringLookupFactory#urlDecoderStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_URL_ENCODER}</td>
* <td>{@link StringLookupFactory#urlEncoderStringLookup()}</td>
* </tr>
* <tr>
* <td>{@value StringLookupFactory#KEY_XML}</td>
* <td>{@link StringLookupFactory#xmlStringLookup()}</td>
* </tr>
* </table>
*
* @return a new instance using the interpolator string lookup.
* @see StringLookupFactory#interpolatorStringLookup()
* @since 1.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
*/
package org.apache.commons.text.lookup;

import java.util.stream.Stream;

/**
* An enumeration defining {@link StringLookup} objects available through {@link StringLookupFactory}.
* <p>
* This enum was adapted and expanded from Apache Commons Configuration 2.4.
* </p>
* <p><strong>NOTE:</strong> Starting in version 1.10.0, not all lookups defined in this class are
* included by default in the
* {@link StringLookupFactory#addDefaultStringLookups(java.util.Map) StringLookupFactory.addDefaultStringLookups}
* method. See the {@link StringLookupFactory} class documentation for details.
* </p>
*
* @see StringLookupFactory
* @see StringLookup
Expand All @@ -31,100 +34,125 @@
public enum DefaultStringLookup {

/**
* The lookup for Base64 decoding using the key {@value StringLookupFactory#KEY_BASE64_DECODER}.
* The lookup for Base64 decoding using the key {@code "base64Decoder"}.
* @see StringLookupFactory#KEY_BASE64_DECODER
* @see StringLookupFactory#base64DecoderStringLookup()
*/
BASE64_DECODER(StringLookupFactory.KEY_BASE64_DECODER, StringLookupFactory.INSTANCE.base64DecoderStringLookup()),

/**
* The lookup for Base64 decoding using the key {@value StringLookupFactory#KEY_BASE64_ENCODER}.
* The lookup for Base64 decoding using the key {@code "base64Encoder"}.
* @see StringLookupFactory#KEY_BASE64_ENCODER
* @see StringLookupFactory#base64EncoderStringLookup()
*/
BASE64_ENCODER(StringLookupFactory.KEY_BASE64_ENCODER, StringLookupFactory.INSTANCE.base64EncoderStringLookup()),

/**
* The lookup for constants using the key {@value StringLookupFactory#KEY_CONST}.
* The lookup for Java static class member constants using the key {@code "const"}.
* @see StringLookupFactory#KEY_CONST
* @see StringLookupFactory#constantStringLookup()
*/
CONST(StringLookupFactory.KEY_CONST, StringLookupFactory.INSTANCE.constantStringLookup()),

/**
* The lookup for dates using the key {@value StringLookupFactory#KEY_DATE}.
* The lookup for formatting the current date using the key {@code "date"}.
* @see StringLookupFactory#KEY_DATE
* @see StringLookupFactory#dateStringLookup()
*/
DATE(StringLookupFactory.KEY_DATE, StringLookupFactory.INSTANCE.dateStringLookup()),

/**
* The lookup for DNS using the key {@value StringLookupFactory#KEY_DNS}.
*
* The lookup for DNS using the key {@code "dns"}.
* @see StringLookupFactory#KEY_DNS
* @see StringLookupFactory#dnsStringLookup()
* @since 1.8
*/
DNS(StringLookupFactory.KEY_DNS, StringLookupFactory.INSTANCE.dnsStringLookup()),

/**
* The lookup for environment properties using the key {@value StringLookupFactory#KEY_ENV}.
* The lookup for environment properties using the key {@code "env"}.
* @see StringLookupFactory#KEY_ENV
* @see StringLookupFactory#environmentVariableStringLookup()
*/
ENVIRONMENT(StringLookupFactory.KEY_ENV, StringLookupFactory.INSTANCE.environmentVariableStringLookup()),

/**
* The lookup for files using the key {@value StringLookupFactory#KEY_FILE}.
* The lookup for files using the key {@code "file"}.
* @see StringLookupFactory#KEY_FILE
* @see StringLookupFactory#fileStringLookup()
*/
FILE(StringLookupFactory.KEY_FILE, StringLookupFactory.INSTANCE.fileStringLookup()),

/**
* The lookup for Java platform information using the key {@value StringLookupFactory#KEY_JAVA}.
* The lookup for Java platform information using the key {@code "java"}.
* @see StringLookupFactory#KEY_JAVA
* @see StringLookupFactory#javaPlatformStringLookup()
*/
JAVA(StringLookupFactory.KEY_JAVA, StringLookupFactory.INSTANCE.javaPlatformStringLookup()),

/**
* The lookup for localhost information using the key {@value StringLookupFactory#KEY_LOCALHOST}.
* The lookup for localhost information using the key {@code "localhost"}.
* @see StringLookupFactory#KEY_LOCALHOST
* @see StringLookupFactory#localHostStringLookup()
*/
LOCAL_HOST(StringLookupFactory.KEY_LOCALHOST, StringLookupFactory.INSTANCE.localHostStringLookup()),

/**
* The lookup for properties using the key {@value StringLookupFactory#KEY_PROPERTIES}.
* The lookup for properties using the key {@code "properties"}.
* @see StringLookupFactory#KEY_PROPERTIES
* @see StringLookupFactory#propertiesStringLookup()
*/
PROPERTIES(StringLookupFactory.KEY_PROPERTIES, StringLookupFactory.INSTANCE.propertiesStringLookup()),

/**
* The lookup for resource bundles using the key {@value StringLookupFactory#KEY_RESOURCE_BUNDLE}.
* The lookup for resource bundles using the key {@code "resourceBundle"}.
* @see StringLookupFactory#KEY_RESOURCE_BUNDLE
* @see StringLookupFactory#resourceBundleStringLookup()
*/
RESOURCE_BUNDLE(StringLookupFactory.KEY_RESOURCE_BUNDLE, StringLookupFactory.INSTANCE.resourceBundleStringLookup()),

/**
* The lookup for scripts using the key {@value StringLookupFactory#KEY_SCRIPT}.
* The lookup for scripts using the key {@code "script"}.
* @see StringLookupFactory#KEY_SCRIPT
* @see StringLookupFactory#scriptStringLookup()
*/
SCRIPT(StringLookupFactory.KEY_SCRIPT, StringLookupFactory.INSTANCE.scriptStringLookup()),

/**
* The lookup for system properties using the key {@value StringLookupFactory#KEY_SYS}.
* The lookup for system properties using the key {@code "sys"}.
* @see StringLookupFactory#KEY_SYS
* @see StringLookupFactory#systemPropertyStringLookup()
*/
SYSTEM_PROPERTIES(StringLookupFactory.KEY_SYS, StringLookupFactory.INSTANCE.systemPropertyStringLookup()),

/**
* The lookup for URLs using the key {@value StringLookupFactory#KEY_URL}.
* The lookup for URLs using the key {@code "url"}.
* @see StringLookupFactory#KEY_URL
* @see StringLookupFactory#urlStringLookup()
*/
URL(StringLookupFactory.KEY_URL, StringLookupFactory.INSTANCE.urlStringLookup()),

/**
* The lookup for URL decoding using the key {@value StringLookupFactory#KEY_URL_DECODER}.
* The lookup for URL decoding using the key {@code "urlDecoder"}.
* @see StringLookupFactory#KEY_URL_DECODER
* @see StringLookupFactory#urlDecoderStringLookup()
*/
URL_DECODER(StringLookupFactory.KEY_URL_DECODER, StringLookupFactory.INSTANCE.urlDecoderStringLookup()),

/**
* The lookup for URL decoding using the key {@value StringLookupFactory#KEY_URL_ENCODER}.
* The lookup for URL decoding using the key {@code "urlEncoder"}.
* @see StringLookupFactory#KEY_URL_ENCODER
* @see StringLookupFactory#urlEncoderStringLookup()
*/
URL_ENCODER(StringLookupFactory.KEY_URL_ENCODER, StringLookupFactory.INSTANCE.urlEncoderStringLookup()),

/**
* The lookup for URL decoding using the key {@value StringLookupFactory#KEY_XML}.
* The lookup for URL decoding using the key {@code "xml"}.
* @see StringLookupFactory#KEY_XML
* @see StringLookupFactory#xmlStringLookup()
*/
XML(StringLookupFactory.KEY_XML, StringLookupFactory.INSTANCE.xmlStringLookup());

/**
* Prints out to the console the mapping from enum keys to enum name.
* @param args ignored.
*/
public static void main(final String[] args) {
Stream.of(values()).forEach(e -> System.out.println(e.getKey() + "=" + e.name()));
}

/** The prefix under which the associated lookup object is registered. */
private final String key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

Expand All @@ -40,10 +39,6 @@ class InterpolatorStringLookup extends AbstractStringLookup {
/** Constant for the prefix separator. */
private static final char PREFIX_SEPARATOR = ':';

static String toKey(final String key) {
return key.toLowerCase(Locale.ROOT);
}

/** The default string lookup. */
private final StringLookup defaultStringLookup;

Expand Down Expand Up @@ -72,7 +67,7 @@ static String toKey(final String key) {
this.defaultStringLookup = defaultStringLookup;
this.stringLookupMap = new HashMap<>(stringLookupMap.size());
for (final Entry<String, StringLookup> entry : stringLookupMap.entrySet()) {
this.stringLookupMap.put(toKey(entry.getKey()), entry.getValue());
this.stringLookupMap.put(StringLookupFactory.toKey(entry.getKey()), entry.getValue());
}
if (addDefaultLookups) {
StringLookupFactory.INSTANCE.addDefaultStringLookups(this.stringLookupMap);
Expand Down Expand Up @@ -127,7 +122,7 @@ public String lookup(String key) {

final int prefixPos = key.indexOf(PREFIX_SEPARATOR);
if (prefixPos >= 0) {
final String prefix = toKey(key.substring(0, prefixPos));
final String prefix = StringLookupFactory.toKey(key.substring(0, prefixPos));
final String name = key.substring(prefixPos + 1);
final StringLookup lookup = stringLookupMap.get(prefix);
String value = null;
Expand Down
Loading

0 comments on commit b9b40b9

Please sign in to comment.