Merge branch 'master' of https://github.com/nickwongwong/commons-text
diff --git a/pom.xml b/pom.xml
index 1c2c720..f79cfd3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,7 +78,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
- <version>3.8</version>
+ <version>3.8.1</version>
</dependency>
<!-- testing -->
<dependency>
@@ -357,6 +357,9 @@
<contributor>
<name>Jan Martin Keil</name>
</contributor>
+ <contributor>
+ <name>Nandor Kollar</name>
+ </contributor>
</contributors>
<scm>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8ff0a07..91d507d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -46,14 +46,19 @@
<body>
<release version="1.5" date="2018-MM-DD" description="Release 1.5">
+ <action issue="TEXT-118" type="fix" dev="chtompki" due-to="Nandor Kollar">JSON escaping incorrect for the delete control character</action>
<action issue="TEXT-130" type="fix" dev="chtompki" due-to="Jan Martin Keil">Fixes JaroWinklerDistance: Wrong results due to precision of transpositions</action>
<action issue="TEXT-131" type="fix" dev="chtompki" due-to="Jan Martin Keil">JaroWinklerDistance: Calculation deviates from definition</action>
- <action issue="TEXT-132" type="update" dev="ggregory">Update Apache Commons Lang from 3.7 to 3.8.</action>
+ <action issue="TEXT-132" type="update" dev="ggregory">Update Apache Commons Lang from 3.7 to 3.8.1</action>
<action issue="TEXT-133" type="add" dev="ggregory">Add a XML file XPath string lookup.</action>
<action issue="TEXT-134" type="add" dev="ggregory">Add a Properties file string lookup.</action>
<action issue="TEXT-135" type="add" dev="ggregory">Add a script string lookup.</action>
<action issue="TEXT-136" type="add" dev="ggregory">Add a file string lookup.</action>
<action issue="TEXT-137" type="add" dev="ggregory">Add a URL string lookup.</action>
+ <action issue="TEXT-140" type="add" dev="ggregory">Add a Base64 string lookup.</action>
+ <action issue="TEXT-141" type="add" dev="ggregory">Add org.apache.commons.text.lookup.StringLookupFactory.resourceBundleStringLookup(String).</action>
+ <action issue="TEXT-142" type="add" dev="ggregory">Add URL encoder and decoder string lookups.</action>
+ <action issue="TEXT-143" type="add" dev="ggregory">Add constant string lookup like the one in Apache Commons Configuration.</action>
</release>
<release version="1.4" date="2018-06-12" description="Release 1.4">
diff --git a/src/main/java/org/apache/commons/text/StrLookup.java b/src/main/java/org/apache/commons/text/StrLookup.java
index 8d3811a..b197e1d 100644
--- a/src/main/java/org/apache/commons/text/StrLookup.java
+++ b/src/main/java/org/apache/commons/text/StrLookup.java
@@ -1,212 +1,213 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.text;
-
-import java.util.Map;
-import java.util.ResourceBundle;
-
-import org.apache.commons.text.lookup.StringLookup;
-import org.apache.commons.text.lookup.StringLookupFactory;
-
-/**
- * Lookup a String key to a String value.
- * <p>
- * This class represents the simplest form of a string to string map. It has a benefit over a map in that it can create
- * the result on demand based on the key.
- * <p>
- * This class comes complete with various factory methods. If these do not suffice, you can subclass and implement your
- * own matcher.
- * <p>
- * For example, it would be possible to implement a lookup that used the key as a primary key, and looked up the value
- * on demand from the database
- *
- * @param <V> the type of the values supported by the lookup
- * @since 1.0
- * @deprecated Deprecated as of 1.3, use {@link StringLookupFactory} instead. This class will be removed in 2.0.
- */
-@Deprecated
-public abstract class StrLookup<V> implements StringLookup {
-
- /**
- * Lookup that always returns null.
- */
- private static final StrLookup<String> NONE_LOOKUP = new MapStrLookup<>(null);
-
- /**
- * Lookup based on system properties.
- */
- private static final StrLookup<String> SYSTEM_PROPERTIES_LOOKUP = new SystemPropertiesStrLookup();
-
- // -----------------------------------------------------------------------
- /**
- * Returns a lookup which always returns null.
- *
- * @return a lookup that always returns null, not null
- */
- public static StrLookup<?> noneLookup() {
- return NONE_LOOKUP;
- }
-
- /**
- * Returns a new lookup which uses a copy of the current {@link System#getProperties() System properties}.
- * <p>
- * If a security manager blocked access to system properties, then null will be returned from every lookup.
- * <p>
- * If a null key is used, this lookup will throw a NullPointerException.
- *
- * @return a lookup using system properties, not null
- */
- public static StrLookup<String> systemPropertiesLookup() {
- return SYSTEM_PROPERTIES_LOOKUP;
- }
-
- /**
- * Returns a lookup which looks up values using a map.
- * <p>
- * If the map is null, then null will be returned from every lookup. The map result object is converted to a string
- * using toString().
- *
- * @param <V> the type of the values supported by the lookup
- * @param map the map of keys to values, may be null
- * @return a lookup using the map, not null
- */
- public static <V> StrLookup<V> mapLookup(final Map<String, V> map) {
- return new MapStrLookup<>(map);
- }
-
- /**
- * Returns a lookup which looks up values using a ResourceBundle.
- * <p>
- * If the ResourceBundle is null, then null will be returned from every lookup. The map result object is converted
- * to a string using toString().
- *
- * @param resourceBundle the map of keys to values, may be null
- * @return a lookup using the map, not null
- */
- public static StrLookup<String> resourceBundleLookup(final ResourceBundle resourceBundle) {
- return new ResourceBundleLookup(resourceBundle);
- }
-
- // -----------------------------------------------------------------------
- /**
- * Constructor.
- */
- protected StrLookup() {
- super();
- }
-
- // -----------------------------------------------------------------------
- /**
- * Lookup implementation that uses a Map.
- *
- * @param <V> the type of the values supported by the lookup
- */
- static class MapStrLookup<V> extends StrLookup<V> {
-
- /** Map keys are variable names and value. */
- private final Map<String, V> map;
-
- /**
- * Creates a new instance backed by a Map.
- *
- * @param map the map of keys to values, may be null
- */
- MapStrLookup(final Map<String, V> map) {
- this.map = map;
- }
-
- /**
- * Looks up a String key to a String value using the map.
- * <p>
- * If the map is null, then null is returned. The map result object is converted to a string using toString().
- *
- * @param key the key to be looked up, may be null
- * @return the matching value, null if no match
- */
- @Override
- public String lookup(final String key) {
- if (map == null) {
- return null;
- }
- final Object obj = map.get(key);
- if (obj == null) {
- return null;
- }
- return obj.toString();
- }
-
- @Override
- public String toString() {
- return super.toString() + " [map=" + map + "]";
- }
- }
-
- // -----------------------------------------------------------------------
- /**
- * Lookup implementation based on a ResourceBundle.
- */
- private static final class ResourceBundleLookup extends StrLookup<String> {
-
- /** ResourceBundle keys are variable names and value. */
- private final ResourceBundle resourceBundle;
-
- /**
- * Creates a new instance backed by a ResourceBundle.
- *
- * @param resourceBundle the ResourceBundle of keys to values, may be null
- */
- private ResourceBundleLookup(final ResourceBundle resourceBundle) {
- this.resourceBundle = resourceBundle;
- }
-
- @Override
- public String lookup(final String key) {
- if (resourceBundle == null || key == null || !resourceBundle.containsKey(key)) {
- return null;
- }
- return resourceBundle.getString(key);
- }
-
- @Override
- public String toString() {
- return super.toString() + " [resourceBundle=" + resourceBundle + "]";
- }
-
- }
-
- // -----------------------------------------------------------------------
- /**
- * Lookup implementation based on system properties.
- */
- private static final class SystemPropertiesStrLookup extends StrLookup<String> {
- /**
- * {@inheritDoc} This implementation directly accesses system properties.
- */
- @Override
- public String lookup(final String key) {
- if (key.length() > 0) {
- try {
- return System.getProperty(key);
- } catch (final SecurityException scex) {
- // Squelched. All lookup(String) will return null.
- return null;
- }
- }
- return null;
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.text;
+
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.apache.commons.text.lookup.StringLookup;
+import org.apache.commons.text.lookup.StringLookupFactory;
+
+/**
+ * Lookup a String key to a String value.
+ * <p>
+ * This class represents the simplest form of a string to string map. It has a benefit over a map in that it can create
+ * the result on demand based on the key.
+ * <p>
+ * This class comes complete with various factory methods. If these do not suffice, you can subclass and implement your
+ * own matcher.
+ * <p>
+ * For example, it would be possible to implement a lookup that used the key as a primary key, and looked up the value
+ * on demand from the database
+ *
+ * @param <V> the type of the values supported by the lookup
+ * @since 1.0
+ * @deprecated Deprecated as of 1.3, use {@link StringLookupFactory} instead. This class will be removed in 2.0.
+ */
+@Deprecated
+public abstract class StrLookup<V> implements StringLookup {
+
+ /**
+ * Lookup that always returns null.
+ */
+ private static final StrLookup<String> NONE_LOOKUP = new MapStrLookup<>(null);
+
+ /**
+ * Lookup based on system properties.
+ */
+ private static final StrLookup<String> SYSTEM_PROPERTIES_LOOKUP = new SystemPropertiesStrLookup();
+
+ // -----------------------------------------------------------------------
+ /**
+ * Returns a lookup which always returns null.
+ *
+ * @return a lookup that always returns null, not null
+ */
+ public static StrLookup<?> noneLookup() {
+ return NONE_LOOKUP;
+ }
+
+ /**
+ * Returns a new lookup which uses a copy of the current {@link System#getProperties() System properties}.
+ * <p>
+ * If a security manager blocked access to system properties, then null will be returned from every lookup.
+ * <p>
+ * If a null key is used, this lookup will throw a NullPointerException.
+ *
+ * @return a lookup using system properties, not null
+ */
+ public static StrLookup<String> systemPropertiesLookup() {
+ return SYSTEM_PROPERTIES_LOOKUP;
+ }
+
+ /**
+ * Returns a lookup which looks up values using a map.
+ * <p>
+ * If the map is null, then null will be returned from every lookup. The map result object is converted to a string
+ * using toString().
+ *
+ * @param <V> the type of the values supported by the lookup
+ * @param map the map of keys to values, may be null
+ * @return a lookup using the map, not null
+ */
+ public static <V> StrLookup<V> mapLookup(final Map<String, V> map) {
+ return new MapStrLookup<>(map);
+ }
+
+ /**
+ * Returns a lookup which looks up values using a ResourceBundle.
+ * <p>
+ * If the ResourceBundle is null, then null will be returned from every lookup. The map result object is converted
+ * to a string using toString().
+ *
+ * @param resourceBundle the map of keys to values, may be null
+ * @return a lookup using the map, not null
+ * @see StringLookupFactory#resourceBundleStringLookup(String)
+ */
+ public static StrLookup<String> resourceBundleLookup(final ResourceBundle resourceBundle) {
+ return new ResourceBundleLookup(resourceBundle);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Constructor.
+ */
+ protected StrLookup() {
+ super();
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Lookup implementation that uses a Map.
+ *
+ * @param <V> the type of the values supported by the lookup
+ */
+ static class MapStrLookup<V> extends StrLookup<V> {
+
+ /** Map keys are variable names and value. */
+ private final Map<String, V> map;
+
+ /**
+ * Creates a new instance backed by a Map.
+ *
+ * @param map the map of keys to values, may be null
+ */
+ MapStrLookup(final Map<String, V> map) {
+ this.map = map;
+ }
+
+ /**
+ * Looks up a String key to a String value using the map.
+ * <p>
+ * If the map is null, then null is returned. The map result object is converted to a string using toString().
+ *
+ * @param key the key to be looked up, may be null
+ * @return the matching value, null if no match
+ */
+ @Override
+ public String lookup(final String key) {
+ if (map == null) {
+ return null;
+ }
+ final Object obj = map.get(key);
+ if (obj == null) {
+ return null;
+ }
+ return obj.toString();
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " [map=" + map + "]";
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Lookup implementation based on a ResourceBundle.
+ */
+ private static final class ResourceBundleLookup extends StrLookup<String> {
+
+ /** ResourceBundle keys are variable names and value. */
+ private final ResourceBundle resourceBundle;
+
+ /**
+ * Creates a new instance backed by a ResourceBundle.
+ *
+ * @param resourceBundle the ResourceBundle of keys to values, may be null
+ */
+ private ResourceBundleLookup(final ResourceBundle resourceBundle) {
+ this.resourceBundle = resourceBundle;
+ }
+
+ @Override
+ public String lookup(final String key) {
+ if (resourceBundle == null || key == null || !resourceBundle.containsKey(key)) {
+ return null;
+ }
+ return resourceBundle.getString(key);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " [resourceBundle=" + resourceBundle + "]";
+ }
+
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Lookup implementation based on system properties.
+ */
+ private static final class SystemPropertiesStrLookup extends StrLookup<String> {
+ /**
+ * {@inheritDoc} This implementation directly accesses system properties.
+ */
+ @Override
+ public String lookup(final String key) {
+ if (key.length() > 0) {
+ try {
+ return System.getProperty(key);
+ } catch (final SecurityException scex) {
+ // Squelched. All lookup(String) will return null.
+ return null;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java
index 3ac66ff..b183233 100644
--- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java
+++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java
@@ -108,7 +108,7 @@
ESCAPE_JSON = new AggregateTranslator(
new LookupTranslator(Collections.unmodifiableMap(escapeJsonMap)),
new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE),
- JavaUnicodeEscaper.outsideOf(32, 0x7f)
+ JavaUnicodeEscaper.outsideOf(32, 0x7e)
);
}
diff --git a/src/main/java/org/apache/commons/text/StringSubstitutor.java b/src/main/java/org/apache/commons/text/StringSubstitutor.java
index 4fcbc4b..58f6e82 100644
--- a/src/main/java/org/apache/commons/text/StringSubstitutor.java
+++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java
@@ -135,6 +135,27 @@
public class StringSubstitutor {
/**
+ * The default variable default separator.
+ *
+ * @since 1.5.
+ */
+ public static final String DEFAULT_VAR_DEFAULT = ":-";
+
+ /**
+ * The default variable end separator.
+ *
+ * @since 1.5.
+ */
+ public static final String DEFAULT_VAR_END = "}";
+
+ /**
+ * The default variable start separator.
+ *
+ * @since 1.5.
+ */
+ public static final String DEFAULT_VAR_START = "${";
+
+ /**
* Constant for the default escape character.
*/
public static final char DEFAULT_ESCAPE = '$';
@@ -142,17 +163,17 @@
/**
* Constant for the default variable prefix.
*/
- public static final StringMatcher DEFAULT_PREFIX = StringMatcherFactory.INSTANCE.stringMatcher("${");
+ public static final StringMatcher DEFAULT_PREFIX = StringMatcherFactory.INSTANCE.stringMatcher(DEFAULT_VAR_START);
/**
* Constant for the default variable suffix.
*/
- public static final StringMatcher DEFAULT_SUFFIX = StringMatcherFactory.INSTANCE.stringMatcher("}");
+ public static final StringMatcher DEFAULT_SUFFIX = StringMatcherFactory.INSTANCE.stringMatcher(DEFAULT_VAR_END);
/**
* Constant for the default value delimiter of a variable.
*/
- public static final StringMatcher DEFAULT_VALUE_DELIMITER = StringMatcherFactory.INSTANCE.stringMatcher(":-");
+ public static final StringMatcher DEFAULT_VALUE_DELIMITER = StringMatcherFactory.INSTANCE.stringMatcher(DEFAULT_VAR_DEFAULT);
// -----------------------------------------------------------------------
/**
diff --git a/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java b/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java
index 404bbdc..4dbdb65 100644
--- a/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java
@@ -24,6 +24,12 @@
*/
abstract class AbstractStringLookup implements StringLookup {
+
+ /**
+ * The empty string.
+ */
+ private static final String EMPTY = "";
+
/**
* The default split char.
*/
@@ -45,7 +51,21 @@
*/
protected String substringAfter(final String value, final char ch) {
final int indexOf = value.indexOf(ch);
- return indexOf > -1 ? value.substring(indexOf + 1) : "";
+ return indexOf > -1 ? value.substring(indexOf + 1) : EMPTY;
+ }
+
+ /**
+ * Returns the substring after the first occurrence of <code>ch</code> in <code>value</code>.
+ *
+ * @param value
+ * The source string.
+ * @param ch
+ * The character to search.
+ * @return a new string.
+ */
+ protected String substringAfterLast(final String value, final char ch) {
+ final int indexOf = value.lastIndexOf(ch);
+ return indexOf > -1 ? value.substring(indexOf + 1) : EMPTY;
}
/**
@@ -59,6 +79,6 @@
*/
protected String substringAfter(final String value, final String str) {
final int indexOf = value.indexOf(str);
- return indexOf > -1 ? value.substring(indexOf + str.length()) : "";
+ return indexOf > -1 ? value.substring(indexOf + str.length()) : EMPTY;
}
}
diff --git a/src/main/java/org/apache/commons/text/lookup/Base64StringLookup.java b/src/main/java/org/apache/commons/text/lookup/Base64StringLookup.java
new file mode 100644
index 0000000..a4651bd
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/Base64StringLookup.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import java.util.Base64;
+
+/**
+ * Decodes Base64 Strings.
+ *
+ * @since 1.5
+ */
+final class Base64StringLookup extends AbstractStringLookup {
+
+ /**
+ * Defines the singleton for this class.
+ */
+ static final Base64StringLookup INSTANCE = new Base64StringLookup();
+
+ /**
+ * No need to build instances for now.
+ */
+ private Base64StringLookup() {
+ // empty
+ }
+
+ @Override
+ public String lookup(final String key) {
+ return new String(Base64.getDecoder().decode(key));
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java
new file mode 100644
index 0000000..96e7855
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/ConstantStringLookup.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import java.lang.reflect.Field;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang3.ClassUtils;
+
+/**
+ * <p>
+ * A specialized lookup implementation that allows access to constant fields of classes.
+ * </p>
+ * <p>
+ * Sometimes it is necessary in a configuration file to refer to a constant defined in a class. This can be done with
+ * this lookup implementation. Variable names passed in must be of the form {@code apackage.AClass.AFIELD}. The
+ * {@code lookup(String)} method will split the passed in string at the last dot, separating the fully qualified class
+ * name and the name of the constant (i.e. <b>static final</b>) member field. Then the class is loaded and the field's
+ * value is obtained using reflection.
+ * </p>
+ * <p>
+ * Once retrieved values are cached for fast access. This class is thread-safe. It can be used as a standard (i.e.
+ * global) lookup object and serve multiple clients concurrently.
+ * </p>
+ * <p>
+ * This class was adapted from Apache Commons Configuration.
+ * </p>
+ *
+ * @since 1.5
+ */
+class ConstantStringLookup extends AbstractStringLookup {
+
+ /** Constant for the field separator. */
+ private static final char FIELD_SEPRATOR = '.';
+
+ /**
+ * Defines the singleton for this class.
+ */
+ static final ConstantStringLookup INSTANCE = new ConstantStringLookup();
+
+ /** An internally used cache for already retrieved values. */
+ private static ConcurrentHashMap<String, String> constantCache = new ConcurrentHashMap<>();
+
+ /**
+ * Clears the shared cache with the so far resolved constants.
+ */
+ static void clear() {
+ constantCache.clear();
+ }
+
+ /**
+ * Tries to resolve the specified variable. The passed in variable name is interpreted as the name of a <b>static
+ * final</b> member field of a class. If the value has already been obtained, it can be retrieved from an internal
+ * cache. Otherwise this method will invoke the {@code resolveField()} method and pass in the name of the class and
+ * the field.
+ *
+ * @param key
+ * the name of the variable to be resolved
+ * @return the value of this variable or <b>null</b> if it cannot be resolved
+ */
+ @Override
+ public synchronized String lookup(final String key) {
+ if (key == null) {
+ return null;
+ }
+ String result;
+ result = constantCache.get(key);
+ if (result != null) {
+ return result;
+ }
+ final int fieldPos = key.lastIndexOf(FIELD_SEPRATOR);
+ if (fieldPos < 0) {
+ return null;
+ }
+ try {
+ final Object value = resolveField(key.substring(0, fieldPos), key.substring(fieldPos + 1));
+ if (value != null) {
+ final String string = Objects.toString(value, null);
+ constantCache.put(key, string);
+ result = string;
+ }
+ } catch (final Exception ex) {
+ // TODO it would be nice to log
+ return null;
+ }
+ return result;
+ }
+
+ /**
+ * Determines the value of the specified constant member field of a class. This implementation will call
+ * {@code fetchClass()} to obtain the {@code java.lang.Class} object for the target class. Then it will use
+ * reflection to obtain the field's value. For this to work the field must be accessable.
+ *
+ * @param className
+ * the name of the class
+ * @param fieldName
+ * the name of the member field of that class to read
+ * @return the field's value
+ * @throws Exception
+ * if an error occurs
+ */
+ protected Object resolveField(final String className, final String fieldName) throws Exception {
+ final Class<?> clazz = fetchClass(className);
+ if (clazz == null) {
+ return null;
+ }
+ final Field field = clazz.getField(fieldName);
+ return field == null ? null : field.get(null);
+ }
+
+ /**
+ * Loads the class with the specified name. If an application has special needs regarding the class loaders to be
+ * used, it can hook in here. This implementation delegates to the {@code getClass()} method of Commons Lang's
+ * <code><a href="http://commons.apache.org/lang/api-release/org/apache/commons/lang/ClassUtils.html">
+ * ClassUtils</a></code>.
+ *
+ * @param className
+ * the name of the class to be loaded
+ * @return the corresponding class object
+ * @throws ClassNotFoundException
+ * if the class cannot be loaded
+ */
+ protected Class<?> fetchClass(final String className) throws ClassNotFoundException {
+ return ClassUtils.getClass(className);
+ }
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java b/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java
index 068ac0a..8f996cb 100644
--- a/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/InterpolatorStringLookup.java
@@ -32,10 +32,14 @@
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
* <li>"localhost" for the {@link LocalHostStringLookup}.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
* </ul>
*/
class InterpolatorStringLookup extends AbstractStringLookup {
@@ -59,12 +63,16 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup} since 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*/
InterpolatorStringLookup() {
@@ -81,12 +89,16 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup} since 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*
* @param <V>
diff --git a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java
index ee7f556..383c10a 100644
--- a/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/JavaPlatformStringLookup.java
@@ -1,147 +1,186 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.commons.text.lookup;
-
-import java.util.Locale;
-
-import org.apache.commons.lang3.StringUtils;
-
-/**
- * Looks up keys related to Java: Java version, JRE version, VM version, and so on.
- *
- * @since 1.3
- */
-final class JavaPlatformStringLookup extends AbstractStringLookup {
-
- /**
- * Defines the singleton for this class.
- */
- static final JavaPlatformStringLookup INSTANCE = new JavaPlatformStringLookup();
-
- /**
- * No need to build instances for now.
- */
- private JavaPlatformStringLookup() {
- // empty
- }
-
- /**
- * Accessible through the Lookup key {@code hardware}.
- *
- * @return hardware processor information.
- */
- String getHardware() {
- return "processors: " + Runtime.getRuntime().availableProcessors() + ", architecture: "
- + getSystemProperty("os.arch") + this.getSystemProperty("-", "sun.arch.data.model")
- + this.getSystemProperty(", instruction sets: ", "sun.cpu.isalist");
- }
-
- /**
- * Accessible through the Lookup key {@code locale}.
- *
- * @return system locale and file encoding information.
- */
- String getLocale() {
- return "default locale: " + Locale.getDefault() + ", platform encoding: " + getSystemProperty("file.encoding");
- }
-
- /**
- * Accessible through the Lookup key {@code os}.
- *
- * @return operating system information.
- */
- String getOperatingSystem() {
- return getSystemProperty("os.name") + " " + getSystemProperty("os.version")
- + getSystemProperty(" ", "sun.os.patch.level") + ", architecture: " + getSystemProperty("os.arch")
- + getSystemProperty("-", "sun.arch.data.model");
- }
-
- /**
- * Accessible through the Lookup key {@code runtime}.
- *
- * @return Java Runtime Environment information.
- */
- String getRuntime() {
- return getSystemProperty("java.runtime.name") + " (build " + getSystemProperty("java.runtime.version")
- + ") from " + getSystemProperty("java.vendor");
- }
-
- /**
- * Gets the given system property.
- *
- * @param name
- * a system property name.
- * @return a system property value.
- */
- private String getSystemProperty(final String name) {
- return SystemPropertyStringLookup.INSTANCE.lookup(name);
- }
-
- /**
- * Gets the given system property.
- *
- * @param prefix
- * the prefix to use for the result string
- * @param name
- * a system property name.
- * @return the prefix + a system property value.
- */
- private String getSystemProperty(final String prefix, final String name) {
- final String value = getSystemProperty(name);
- if (StringUtils.isEmpty(value)) {
- return StringUtils.EMPTY;
- }
- return prefix + value;
- }
-
- /**
- * Accessible through the Lookup key {@code vm}.
- *
- * @return Java Virtual Machine information.
- */
- String getVirtualMachine() {
- return getSystemProperty("java.vm.name") + " (build " + getSystemProperty("java.vm.version") + ", "
- + getSystemProperty("java.vm.info") + ")";
- }
-
- /**
- * Looks up the value of the Java platform key.
- *
- * @param key
- * the key to be looked up, may be null
- * @return The value of the environment variable.
- */
- @Override
- public String lookup(final String key) {
- switch (key) {
- case "version":
- return "Java version " + getSystemProperty("java.version");
- case "runtime":
- return getRuntime();
- case "vm":
- return getVirtualMachine();
- case "os":
- return getOperatingSystem();
- case "hardware":
- return getHardware();
- case "locale":
- return getLocale();
- default:
- throw new IllegalArgumentException(key);
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.commons.text.lookup;
+
+import java.util.Locale;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Looks up keys related to Java: Java version, JRE version, VM version, and so on.
+ * <p>
+ * The lookup keys with examples are:
+ * </p>
+ * <ul>
+ * <li><b>version</b>: "Java version 1.8.0_181"</li>
+ * <li><b>runtime</b>: "Java(TM) SE Runtime Environment (build 1.8.0_181-b13) from Oracle Corporation"</li>
+ * <li><b>vm</b>: "Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)"</li>
+ * <li><b>os</b>: "Windows 10 10.0, architecture: amd64-64"</li>
+ * <li><b>hardware</b>: "processors: 4, architecture: amd64-64, instruction sets: amd64"</li>
+ * <li><b>locale</b>: "default locale: en_US, platform encoding: iso-8859-1"</li>
+ * </ul>
+ *
+ * @since 1.3
+ */
+final class JavaPlatformStringLookup extends AbstractStringLookup {
+
+ private static final String KEY_LOCALE = "locale";
+ private static final String KEY_HARDWARE = "hardware";
+ private static final String KEY_OS = "os";
+ private static final String KEY_VM = "vm";
+ private static final String KEY_RUNTIME = "runtime";
+ private static final String KEY_VERSION = "version";
+
+ /**
+ * Defines the singleton for this class.
+ */
+ static final JavaPlatformStringLookup INSTANCE = new JavaPlatformStringLookup();
+
+ public static void main(String[] args) {
+ System.out.println(JavaPlatformStringLookup.class);
+ System.out.printf("%s = %s\n", KEY_VERSION, JavaPlatformStringLookup.INSTANCE.lookup(KEY_VERSION));
+ System.out.printf("%s = %s\n", KEY_RUNTIME, JavaPlatformStringLookup.INSTANCE.lookup(KEY_RUNTIME));
+ System.out.printf("%s = %s\n", KEY_VM, JavaPlatformStringLookup.INSTANCE.lookup(KEY_VM));
+ System.out.printf("%s = %s\n", KEY_OS, JavaPlatformStringLookup.INSTANCE.lookup(KEY_OS));
+ System.out.printf("%s = %s\n", KEY_HARDWARE, JavaPlatformStringLookup.INSTANCE.lookup(KEY_HARDWARE));
+ System.out.printf("%s = %s\n", KEY_LOCALE, JavaPlatformStringLookup.INSTANCE.lookup(KEY_LOCALE));
+ }
+
+ /**
+ * No need to build instances for now.
+ */
+ private JavaPlatformStringLookup() {
+ // empty
+ }
+
+ /**
+ * Accessible through the Lookup key {@code hardware}.
+ *
+ * @return hardware processor information.
+ */
+ String getHardware() {
+ return "processors: " + Runtime.getRuntime().availableProcessors() + ", architecture: "
+ + getSystemProperty("os.arch") + this.getSystemProperty("-", "sun.arch.data.model")
+ + this.getSystemProperty(", instruction sets: ", "sun.cpu.isalist");
+ }
+
+ /**
+ * Accessible through the Lookup key {@code locale}.
+ *
+ * @return system locale and file encoding information.
+ */
+ String getLocale() {
+ return "default locale: " + Locale.getDefault() + ", platform encoding: " + getSystemProperty("file.encoding");
+ }
+
+ /**
+ * Accessible through the Lookup key {@code os}.
+ *
+ * @return operating system information.
+ */
+ String getOperatingSystem() {
+ return getSystemProperty("os.name") + " " + getSystemProperty("os.version")
+ + getSystemProperty(" ", "sun.os.patch.level") + ", architecture: " + getSystemProperty("os.arch")
+ + getSystemProperty("-", "sun.arch.data.model");
+ }
+
+ /**
+ * Accessible through the Lookup key {@code runtime}.
+ *
+ * @return Java Runtime Environment information.
+ */
+ String getRuntime() {
+ return getSystemProperty("java.runtime.name") + " (build " + getSystemProperty("java.runtime.version")
+ + ") from " + getSystemProperty("java.vendor");
+ }
+
+ /**
+ * Gets the given system property.
+ *
+ * @param name
+ * a system property name.
+ * @return a system property value.
+ */
+ private String getSystemProperty(final String name) {
+ return SystemPropertyStringLookup.INSTANCE.lookup(name);
+ }
+
+ /**
+ * Gets the given system property.
+ *
+ * @param prefix
+ * the prefix to use for the result string
+ * @param name
+ * a system property name.
+ * @return the prefix + a system property value.
+ */
+ private String getSystemProperty(final String prefix, final String name) {
+ final String value = getSystemProperty(name);
+ if (StringUtils.isEmpty(value)) {
+ return StringUtils.EMPTY;
+ }
+ return prefix + value;
+ }
+
+ /**
+ * Accessible through the Lookup key {@code vm}.
+ *
+ * @return Java Virtual Machine information.
+ */
+ String getVirtualMachine() {
+ return getSystemProperty("java.vm.name") + " (build " + getSystemProperty("java.vm.version") + ", "
+ + getSystemProperty("java.vm.info") + ")";
+ }
+
+ /**
+ * Looks up the value of the Java platform key.
+ * <p>
+ * The lookup keys with examples are:
+ * </p>
+ * <ul>
+ * <li><b>version</b>: "Java version 1.8.0_181"</li>
+ * <li><b>runtime</b>: "Java(TM) SE Runtime Environment (build 1.8.0_181-b13) from Oracle Corporation"</li>
+ * <li><b>vm</b>: "Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)"</li>
+ * <li><b>os</b>: "Windows 10 10.0, architecture: amd64-64"</li>
+ * <li><b>hardware</b>: "processors: 4, architecture: amd64-64, instruction sets: amd64"</li>
+ * <li><b>locale</b>: "default locale: en_US, platform encoding: iso-8859-1"</li>
+ * </ul>
+ *
+ * @param key
+ * the key to be looked up, may be null
+ * @return The value of the environment variable.
+ */
+ @Override
+ public String lookup(final String key) {
+ switch (key) {
+ case KEY_VERSION:
+ return "Java version " + getSystemProperty("java.version");
+ case KEY_RUNTIME:
+ return getRuntime();
+ case KEY_VM:
+ return getVirtualMachine();
+ case KEY_OS:
+ return getOperatingSystem();
+ case KEY_HARDWARE:
+ return getHardware();
+ case KEY_LOCALE:
+ return getLocale();
+ default:
+ throw new IllegalArgumentException(key);
+ }
+ }
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java
index 9e3e6d5..8a14c1b 100644
--- a/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/ResourceBundleStringLookup.java
@@ -33,6 +33,8 @@
*/
final class ResourceBundleStringLookup extends AbstractStringLookup {
+ private final String bundleName;
+
/**
* Defines the singleton for this class.
*/
@@ -42,7 +44,16 @@
* No need to build instances for now.
*/
private ResourceBundleStringLookup() {
- // empty
+ this(null);
+ }
+
+ /**
+ * Constructs an instance that only works for the given bundle.
+ *
+ * @since 1.5
+ */
+ ResourceBundleStringLookup(final String bundleName) {
+ this.bundleName = bundleName;
}
/**
@@ -62,20 +73,24 @@
if (key == null) {
return null;
}
- final String[] keys = key.split(":");
+ final String[] keys = key.split(SPLIT_STR);
final int keyLen = keys.length;
- if (keyLen != 2) {
+ final boolean anyBundle = bundleName == null;
+ if (anyBundle && keyLen != 2) {
throw IllegalArgumentExceptions
.format("Bad resource bundle key format [%s]; expected format is BundleName:KeyName.", key);
+ } else if (bundleName != null && keyLen != 1) {
+ throw IllegalArgumentExceptions.format("Bad resource bundle key format [%s]; expected format is KeyName.",
+ key);
}
- final String bundleName = keys[0];
- final String bundleKey = keys[1];
+ final String keyBundleName = anyBundle ? keys[0] : bundleName;
+ final String bundleKey = anyBundle ? keys[1] : keys[0];
try {
// The ResourceBundle class caches bundles, no need to cache here.
- return ResourceBundle.getBundle(bundleName).getString(bundleKey);
+ return ResourceBundle.getBundle(keyBundleName).getString(bundleKey);
} catch (final Exception e) {
- throw IllegalArgumentExceptions.format(e, "Error looking up resource bundle [%s] and key [%s].", bundleName,
- bundleKey);
+ throw IllegalArgumentExceptions.format(e, "Error looking up resource bundle [%s] and key [%s].",
+ keyBundleName, bundleKey);
}
}
diff --git a/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java b/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java
index 99f1be9..c80e88c 100644
--- a/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/ScriptStringLookup.java
@@ -62,7 +62,7 @@
if (key == null) {
return null;
}
- final String[] keys = key.split(":");
+ final String[] keys = key.split(SPLIT_STR);
final int keyLen = keys.length;
if (keyLen != 2) {
throw IllegalArgumentExceptions
diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
index 25f6596..dcf599d 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
@@ -32,6 +32,15 @@
public static final StringLookupFactory INSTANCE = new StringLookupFactory();
/**
+ * Clears any static resources.
+ *
+ * @since 1.5
+ */
+ public static void clear() {
+ ConstantStringLookup.clear();
+ }
+
+ /**
* No need to build instances for now.
*/
private StringLookupFactory() {
@@ -45,12 +54,16 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup} since 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*
* @param stringLookupMap
@@ -69,6 +82,10 @@
stringLookupMap.put("script", ScriptStringLookup.INSTANCE);
stringLookupMap.put("file", FileStringLookup.INSTANCE);
stringLookupMap.put("url", UrlStringLookup.INSTANCE);
+ stringLookupMap.put("base64", Base64StringLookup.INSTANCE);
+ stringLookupMap.put("urlEncode", UrlEncoderStringLookup.INSTANCE);
+ stringLookupMap.put("urlDecode", UrlDecoderStringLookup.INSTANCE);
+ stringLookupMap.put("const", ConstantStringLookup.INSTANCE);
}
}
@@ -78,6 +95,26 @@
*
* @return the DateStringLookup singleton instance.
*/
+ public StringLookup base64StringLookup() {
+ return Base64StringLookup.INSTANCE;
+ }
+
+ /**
+ * Returns the ConstantStringLookup singleton instance to get the value of a fully-qualified static final value.
+ *
+ * @return the DateStringLookup singleton instance.
+ * @since 1.5
+ */
+ public StringLookup constantStringLookup() {
+ return ConstantStringLookup.INSTANCE;
+ }
+
+ /**
+ * Returns the DateStringLookup singleton instance to format the current date with the format given in the key in a
+ * format compatible with {@link java.text.SimpleDateFormat}.
+ *
+ * @return the DateStringLookup singleton instance.
+ */
public StringLookup dateStringLookup() {
return DateStringLookup.INSTANCE;
}
@@ -118,12 +155,17 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names; since
+ * 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*
* @return a new InterpolatorStringLookup.
@@ -143,12 +185,17 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names; since
+ * 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*
* @param stringLookupMap
@@ -175,12 +222,17 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names; since
+ * 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*
* @param <V>
@@ -203,12 +255,17 @@
* <li>"env" for the {@link EnvironmentVariableStringLookup}.</li>
* <li>"java" for the {@link JavaPlatformStringLookup}.</li>
* <li>"date" for the {@link DateStringLookup}.</li>
- * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names.</li>
- * <li>"xml" for the {@link XmlStringLookup}.</li>
- * <li>"properties" for the {@link PropertiesStringLookup}.</li>
- * <li>"script" for the {@link ScriptStringLookup}.</li>
- * <li>"file" for the {@link FileStringLookup}.</li>
- * <li>"url" for the {@link UrlStringLookup}.</li>
+ * <li>"localhost" for the {@link LocalHostStringLookup}, see {@link #localHostStringLookup()} for key names; since
+ * 1.3.</li>
+ * <li>"xml" for the {@link XmlStringLookup} since 1.5.</li>
+ * <li>"properties" for the {@link PropertiesStringLookup} since 1.5.</li>
+ * <li>"script" for the {@link ScriptStringLookup} since 1.5.</li>
+ * <li>"file" for the {@link FileStringLookup} since 1.5.</li>
+ * <li>"url" for the {@link UrlStringLookup} since 1.5.</li>
+ * <li>"base64" for the {@link Base64StringLookup} since 1.5.</li>
+ * <li>"urlEncode" for the {@link UrlEncoderStringLookup} since 1.5.</li>
+ * <li>"urlDecode" for the {@link UrlDecoderStringLookup} since 1.5.</li>
+ * <li>"const" for the {@link ConstantStringLookup} since 1.5.</li>
* </ul>
*
* @param defaultStringLookup
@@ -220,7 +277,19 @@
}
/**
- * Returns the JavaPlatformStringLookup singleton instance.
+ * Returns the JavaPlatformStringLookup singleton instance. Looks up keys related to Java: Java version, JRE
+ * version, VM version, and so on.
+ * <p>
+ * The lookup keys with examples are:
+ * </p>
+ * <ul>
+ * <li><b>version</b>: "Java version 1.8.0_181"</li>
+ * <li><b>runtime</b>: "Java(TM) SE Runtime Environment (build 1.8.0_181-b13) from Oracle Corporation"</li>
+ * <li><b>vm</b>: "Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)"</li>
+ * <li><b>os</b>: "Windows 10 10.0, architecture: amd64-64"</li>
+ * <li><b>hardware</b>: "processors: 4, architecture: amd64-64, instruction sets: amd64"</li>
+ * <li><b>locale</b>: "default locale: en_US, platform encoding: iso-8859-1"</li>
+ * </ul>
*
* @return the JavaPlatformStringLookup singleton instance.
*/
@@ -296,6 +365,24 @@
}
/**
+ * Returns a ResourceBundleStringLookup instance for the given bundle name.
+ * <p>
+ * Looks up the value for a given key in the format "BundleKey".
+ * </p>
+ * <p>
+ * For example: "MyKey".
+ * </p>
+ *
+ * @param bundleName
+ * Only lookup in this bundle.
+ * @return a ResourceBundleStringLookup instance for the given bundle name.
+ * @since 1.5
+ */
+ public StringLookup resourceBundleStringLookup(final String bundleName) {
+ return new ResourceBundleStringLookup(bundleName);
+ }
+
+ /**
* Returns the ScriptStringLookup singleton instance.
* <p>
* Looks up the value for the key in the format "ScriptEngineName:Script".
diff --git a/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java
new file mode 100644
index 0000000..55a2807
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/UrlDecoderStringLookup.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Decodes URL Strings using the UTF-8 encoding.
+ *
+ * @see URLEncoder
+ * @since 1.5
+ */
+final class UrlDecoderStringLookup extends AbstractStringLookup {
+
+ /**
+ * Defines the singleton for this class.
+ */
+ static final UrlDecoderStringLookup INSTANCE = new UrlDecoderStringLookup();
+
+ /**
+ * No need to build instances for now.
+ */
+ private UrlDecoderStringLookup() {
+ // empty
+ }
+
+ @Override
+ public String lookup(final String key) {
+ final String enc = StandardCharsets.UTF_8.name();
+ try {
+ return new String(URLDecoder.decode(key, enc));
+ } catch (final UnsupportedEncodingException e) {
+ throw IllegalArgumentExceptions.format(e, "%s: source=%s, encoding=%s", e, key, enc);
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java
new file mode 100644
index 0000000..fdc2c1f
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/UrlEncoderStringLookup.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Encodes URL Strings using the UTF-8 encoding.
+ *
+ * @see URLEncoder
+ * @since 1.5
+ */
+final class UrlEncoderStringLookup extends AbstractStringLookup {
+
+ /**
+ * Defines the singleton for this class.
+ */
+ static final UrlEncoderStringLookup INSTANCE = new UrlEncoderStringLookup();
+
+ /**
+ * No need to build instances for now.
+ */
+ private UrlEncoderStringLookup() {
+ // empty
+ }
+
+ @Override
+ public String lookup(final String key) {
+ final String enc = StandardCharsets.UTF_8.name();
+ try {
+ return new String(URLEncoder.encode(key, enc));
+ } catch (final UnsupportedEncodingException e) {
+ throw IllegalArgumentExceptions.format(e, "%s: source=%s, encoding=%s", e, key, enc);
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java b/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java
index 6e0d4d4..1c27736 100644
--- a/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/UrlStringLookup.java
@@ -62,7 +62,7 @@
if (key == null) {
return null;
}
- final String[] keys = key.split(":");
+ final String[] keys = key.split(SPLIT_STR);
final int keyLen = keys.length;
if (keyLen < 2) {
throw IllegalArgumentExceptions.format("Bad URL key format [%s]; expected format is DocumentPath:Key.",
diff --git a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
index 2d36c13..e9abe7b 100644
--- a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
+++ b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
@@ -633,4 +633,10 @@
assertEquals(jsonString, StringEscapeUtils.unescapeJson(escapedJsonString));
}
+
+ @Test
+ public void testDeleteCharacter() {
+ String deleteString = "Delete: \u007F";
+ assertEquals("Delete: \\u007F", StringEscapeUtils.escapeJson(deleteString));
+ }
}
diff --git a/src/test/java/org/apache/commons/text/lookup/Base64StringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/Base64StringLookupTest.java
new file mode 100644
index 0000000..19b61db
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/Base64StringLookupTest.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class Base64StringLookupTest {
+
+ @Test
+ public void test() {
+ Assertions.assertEquals("HelloWorld!", Base64StringLookup.INSTANCE.lookup("SGVsbG9Xb3JsZCE="));
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java
new file mode 100644
index 0000000..ded4c3b
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupBasicTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link ConstantStringLookup}.
+ */
+public class ConstantStringLookupBasicTest {
+
+ /**
+ * Test fixture.
+ */
+ public static final String STRING_FIXTURE = "Hello World!";
+
+ /**
+ * Clears the test environment. Here the static cache of the constant lookup class is wiped out.
+ */
+ @AfterEach
+ public void afterEach() {
+ ConstantStringLookup.clear();
+ }
+
+ /**
+ * Clears the test environment. Here the static cache of the constant lookup class is wiped out.
+ */
+ @BeforeEach
+ public void beforeEach() {
+ ConstantStringLookup.clear();
+ }
+
+ @Test
+ public void testOne() {
+ Assertions.assertEquals(STRING_FIXTURE, ConstantStringLookup.INSTANCE
+ .lookup(ConstantStringLookupBasicTest.class.getName() + ".STRING_FIXTURE"));
+ }
+}
diff --git a/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java
new file mode 100644
index 0000000..fb1c4ca
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/ConstantStringLookupTest.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.text.lookup;
+
+import java.awt.event.KeyEvent;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link ConstantStringLookup}.
+ * <p>
+ * This class was adapted from Apache Commons Configuration.
+ * </p>
+ */
+public class ConstantStringLookupTest {
+
+ /** A public field that can be read by the lookup. */
+ public static final String FIELD = "Field that can be read";
+
+ /** A private field that cannot be read by the lookup. */
+ @SuppressWarnings("unused")
+ private static final String PRIVATE_FIELD = "PRIVATE";
+
+ /** The lookup object to be tested. */
+ private ConstantStringLookup stringLookup;
+
+ /**
+ * Clears the test environment. Here the static cache of the constant lookup class is wiped out.
+ */
+ @AfterEach
+ public void afterEach() {
+ ConstantStringLookup.clear();
+ }
+
+ /**
+ * Clears the test environment. Here the static cache of the constant lookup class is wiped out.
+ */
+ @BeforeEach
+ public void beforeEach() {
+ stringLookup = ConstantStringLookup.INSTANCE;
+ }
+
+ /**
+ * Tests accessing the cache by querying a variable twice.
+ */
+ @Test
+ public void testLookupCache() {
+ testLookupConstant();
+ testLookupConstant();
+ }
+
+ /**
+ * Tests resolving a valid constant.
+ */
+ @Test
+ public void testLookupConstant() {
+ Assertions.assertEquals(FIELD, stringLookup.lookup(variable("FIELD")), "Wrong value of constant");
+ }
+
+ /**
+ * Tries to resolve a variable with an invalid syntax: The name does not contain a dot as a field separator.
+ */
+ @Test
+ public void testLookupInvalidSyntax() {
+ Assertions.assertNull(stringLookup.lookup("InvalidVariableName"),
+ "Non null return value for invalid variable name");
+ }
+
+ /**
+ * Tests resolving a non existing constant. Result should be null.
+ */
+ @Test
+ public void testLookupNonExisting() {
+ Assertions.assertNull(stringLookup.lookup(variable("NO_FIELD")),
+ "Non null return value for non existing constant");
+ }
+
+ /**
+ * Tests resolving a non string constant. Then looks the same variable up from the cache.
+ */
+ @Test
+ public void testLookupNonString() {
+ final String ref = KeyEvent.class.getName() + ".VK_ESCAPE";
+ final String expected = Integer.toString(KeyEvent.VK_ESCAPE);
+ Assertions.assertEquals(expected, stringLookup.lookup(ref), "Wrong result of first lookup");
+ Assertions.assertEquals(expected, stringLookup.lookup(ref), "Wrong result of 2nd lookup");
+ }
+
+ /**
+ * Tests looking up a null variable.
+ */
+ @Test
+ public void testLookupNull() {
+ Assertions.assertNull(stringLookup.lookup(null), "Non null return value for null variable");
+ }
+
+ /**
+ * Tests resolving a private constant. Because a private field cannot be accessed this should again yield null.
+ */
+ @Test
+ public void testLookupPrivate() {
+ Assertions.assertNull(stringLookup.lookup(variable("PRIVATE_FIELD")),
+ "Non null return value for non accessible field");
+ }
+
+ /**
+ * Tests resolving a field from an unknown class.
+ */
+ @Test
+ public void testLookupUnknownClass() {
+ Assertions.assertNull(stringLookup.lookup("org.apache.commons.configuration.NonExistingConfig." + FIELD),
+ "Non null return value for unknown class");
+ }
+
+ /**
+ * Generates the name of a variable for a lookup operation based on the given field name of this class.
+ *
+ * @param field
+ * the field name
+ * @return the variable for looking up this field
+ */
+ private String variable(final String field) {
+ return getClass().getName() + '.' + field;
+ }
+}
diff --git a/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java
index 37415b5..0b5c4d9 100644
--- a/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java
+++ b/src/test/java/org/apache/commons/text/lookup/ResourceBundleStringLookupTest.java
@@ -25,11 +25,19 @@
public class ResourceBundleStringLookupTest {
@Test
- public void testOne() {
+ public void testAny() {
final String bundleName = "testResourceBundleLookup";
final String bundleKey = "key";
Assertions.assertEquals(ResourceBundle.getBundle(bundleName).getString(bundleKey),
ResourceBundleStringLookup.INSTANCE.lookup(bundleName + ":" + bundleKey));
}
+ @Test
+ public void testOne() {
+ final String bundleName = "testResourceBundleLookup";
+ final String bundleKey = "key";
+ Assertions.assertEquals(ResourceBundle.getBundle(bundleName).getString(bundleKey),
+ new ResourceBundleStringLookup(bundleName).lookup(bundleKey));
+ }
+
}
diff --git a/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java
new file mode 100644
index 0000000..9fc628c
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/UrlDecoderStringLookupTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link UrlDecoderStringLookup}.
+ */
+public class UrlDecoderStringLookupTest {
+
+ @Test
+ public void testAllPercent() {
+ Assertions.assertEquals("Hello World!", UrlDecoderStringLookup.INSTANCE.lookup("Hello%20World%21"));
+ }
+
+ @Test
+ public void testExclamation() {
+ Assertions.assertEquals("Hello World!", UrlDecoderStringLookup.INSTANCE.lookup("Hello%20World!"));
+ }
+
+ @Test
+ public void testPlus() {
+ Assertions.assertEquals("Hello World!", UrlDecoderStringLookup.INSTANCE.lookup("Hello+World!"));
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java
new file mode 100644
index 0000000..c73c591
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/UrlEncoderStringLookupTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.commons.text.lookup;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link UrlEncoderStringLookup}.
+ */
+public class UrlEncoderStringLookupTest {
+
+ @Test
+ public void test() {
+ Assertions.assertEquals("Hello+World%21", UrlEncoderStringLookup.INSTANCE.lookup("Hello World!"));
+ }
+
+}