    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements. See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache license, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License. You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the license for the specific language governing permissions and
    015 * limitations under the license.
    016 */
    017
    018package org.apache.commons.text.lookup;
    019
    020import java.util.Map;
    021
    022import org.apache.commons.text.StringSubstitutor;
    023
    024/**
    025 * Provides access to lookups defined in this package.
    026 * <p>
    027 * The default lookups are:
    028 * </p>
    029 * <table>
    030 * <caption>Default String Lookups</caption>
    031 * <tr>
    032 * <th>Key</th>
    033 * <th>Implementation</th>
    034 * <th>Factory Method</th>
    035 * <th>Since</th>
    036 * </tr>
    037 * <tr>
    038 * <td>{@value #KEY_BASE64_DECODER}</td>
    039 * <td>{@link Base64DecoderStringLookup}</td>
    040 * <td>{@link #base64DecoderStringLookup()}</td>
    041 * <td>1.6</td>
    042 * </tr>
    043 * <tr>
    044 * <td>{@value #KEY_BASE64_ENCODER}</td>
    045 * <td>{@link Base64EncoderStringLookup}</td>
    046 * <td>{@link #base64EncoderStringLookup()}</td>
    047 * <td>1.6</td>
    048 * </tr>
    049 * <tr>
    050 * <td>{@value #KEY_CONST}</td>
    051 * <td>{@link ConstantStringLookup}</td>
    052 * <td>{@link #constantStringLookup()}</td>
    053 * <td>1.5</td>
    054 * </tr>
    055 * <tr>
    056 * <td>{@value #KEY_DATE}</td>
    057 * <td>{@link DateStringLookup}</td>
    058 * <td>{@link #dateStringLookup()}</td>
    059 * <td>1.5</td>
    060 * </tr>
    061 * <tr>
    062 * <td>{@value #KEY_DNS}</td>
    063 * <td>{@link DnsStringLookup}</td>
    064 * <td>{@link #dnsStringLookup()}</td>
    065 * <td>1.8</td>
    066 * </tr>
    067 * <tr>
    068 * <td>{@value #KEY_ENV}</td>
    069 * <td>{@link EnvironmentVariableStringLookup}</td>
    070 * <td>{@link #environmentVariableStringLookup()}</td>
    071 * <td>1.3</td>
    072 * </tr>
    073 * <tr>
    074 * <td>{@value #KEY_FILE}</td>
    075 * <td>{@link FileStringLookup}</td>
    076 * <td>{@link #fileStringLookup()}</td>
    077 * <td>1.5</td>
    078 * </tr>
    079 * <tr>
    080 * <td>{@value #KEY_JAVA}</td>
    081 * <td>{@link JavaPlatformStringLookup}</td>
    082 * <td>{@link #javaPlatformStringLookup()}</td>
    083 * <td>1.5</td>
    084 * </tr>
    085 * <tr>
    086 * <td>{@value #KEY_LOCALHOST}</td>
    087 * <td>{@link LocalHostStringLookup}</td>
    088 * <td>{@link #localHostStringLookup()}</td>
    089 * <td>1.3</td>
    090 * </tr>
    091 * <tr>
    092 * <td>{@value #KEY_PROPERTIES}</td>
    093 * <td>{@link PropertiesStringLookup}</td>
    094 * <td>{@link #propertiesStringLookup()}</td>
    095 * <td>1.5</td>
    096 * </tr>
    097 * <tr>
    098 * <td>{@value #KEY_RESOURCE_BUNDLE}</td>
    099 * <td>{@link ResourceBundleStringLookup}</td>
    100 * <td>{@link #resourceBundleStringLookup()}</td>
    101 * <td>1.6</td>
    102 * </tr>
    103 * <tr>
    104 * <td>{@value #KEY_SCRIPT}</td>
    105 * <td>{@link ScriptStringLookup}</td>
    106 * <td>{@link #scriptStringLookup()}</td>
    107 * <td>1.5</td>
    108 * </tr>
    109 * <tr>
    110 * <td>{@value #KEY_SYS}</td>
    111 * <td>{@link SystemPropertyStringLookup}</td>
    112 * <td>{@link #systemPropertyStringLookup()}</td>
    113 * <td>1.3</td>
    114 * </tr>
    115 * <tr>
    116 * <td>{@value #KEY_URL}</td>
    117 * <td>{@link UrlStringLookup}</td>
    118 * <td>{@link #urlStringLookup()}</td>
    119 * <td>1.5</td>
    120 * </tr>
    121 * <tr>
    122 * <td>{@value #KEY_URL_DECODER}</td>
    123 * <td>{@link UrlDecoderStringLookup}</td>
    124 * <td>{@link #urlDecoderStringLookup()}</td>
    125 * <td>1.5</td>
    126 * </tr>
    127 * <tr>
    128 * <td>{@value #KEY_URL_ENCODER}</td>
    129 * <td>{@link UrlEncoderStringLookup}</td>
    130 * <td>{@link #urlEncoderStringLookup()}</td>
    131 * <td>1.5</td>
    132 * </tr>
    133 * <tr>
    134 * <td>{@value #KEY_XML}</td>
    135 * <td>{@link XmlStringLookup}</td>
    136 * <td>{@link #xmlStringLookup()}</td>
    137 * <td>1.5</td>
    138 * </tr>
    139 * </table>
    140 *
    141 * @since 1.3
    142 */
    143public final class StringLookupFactory {
    144
    145    /**
    146     * Defines the singleton for this class.
    147     */
    148    public static final StringLookupFactory INSTANCE = new StringLookupFactory();
    149
    150    /**
    151     * Default lookup key for interpolation {@value #KEY_BASE64_DECODER}.
    152     *
    153     * @since 1.6
    154     */
    155    public static final String KEY_BASE64_DECODER = "base64Decoder";
    156
    157    /**
    158     * Default lookup key for interpolation {@value #KEY_BASE64_ENCODER}.
    159     *
    160     * @since 1.6
    161     */
    162    public static final String KEY_BASE64_ENCODER = "base64Encoder";
    163
    164    /**
    165     * Default lookup key for interpolation {@value #KEY_CONST}.
    166     *
    167     * @since 1.6
    168     */
    169    public static final String KEY_CONST = "const";
    170
    171    /**
    172     * Default lookup key for interpolation {@value #KEY_DATE}.
    173     *
    174     * @since 1.6
    175     */
    176    public static final String KEY_DATE = "date";
    177
    178    /**
    179     * Default lookup key for interpolation {@value #KEY_DNS}.
    180     *
    181     * @since 1.8
    182     */
    183    public static final String KEY_DNS = "dns";
    184
    185    /**
    186     * Default lookup key for interpolation {@value #KEY_ENV}.
    187     *
    188     * @since 1.6
    189     */
    190    public static final String KEY_ENV = "env";
    191
    192    /**
    193     * Default lookup key for interpolation {@value #KEY_FILE}.
    194     *
    195     * @since 1.6
    196     */
    197    public static final String KEY_FILE = "file";
    198
    199    /**
    200     * Default lookup key for interpolation {@value #KEY_JAVA}.
    201     *
    202     * @since 1.6
    203     */
    204    public static final String KEY_JAVA = "java";
    205
    206    /**
    207     * Default lookup key for interpolation {@value #KEY_LOCALHOST}.
    208     *
    209     * @since 1.6
    210     */
    211    public static final String KEY_LOCALHOST = "localhost";
    212
    213    /**
    214     * Default lookup key for interpolation {@value #KEY_PROPERTIES}.
    215     *
    216     * @since 1.6
    217     */
    218    public static final String KEY_PROPERTIES = "properties";
    219
    220    /**
    221     * Default lookup key for interpolation {@value #KEY_RESOURCE_BUNDLE}.
    222     *
    223     * @since 1.6
    224     */
    225    public static final String KEY_RESOURCE_BUNDLE = "resourceBundle";
    226
    227    /**
    228     * Default lookup key for interpolation {@value #KEY_SCRIPT}.
    229     *
    230     * @since 1.6
    231     */
    232    public static final String KEY_SCRIPT = "script";
    233
    234    /**
    235     * Default lookup key for interpolation {@value #KEY_SYS}.
    236     *
    237     * @since 1.6
    238     */
    239    public static final String KEY_SYS = "sys";
    240
    241    /**
    242     * Default lookup key for interpolation {@value #KEY_URL}.
    243     *
    244     * @since 1.6
    245     */
    246    public static final String KEY_URL = "url";
    247
    248    /**
    249     * Default lookup key for interpolation {@value #KEY_URL_DECODER}.
    250     *
    251     * @since 1.6
    252     */
    253    public static final String KEY_URL_DECODER = "urlDecoder";
    254
    255    /**
    256     * Default lookup key for interpolation {@value #KEY_URL_ENCODER}.
    257     *
    258     * @since 1.6
    259     */
    260    public static final String KEY_URL_ENCODER = "urlEncoder";
    261
    262    /**
    263     * Default lookup key for interpolation {@value #KEY_XML}.
    264     *
    265     * @since 1.6
    266     */
    267    public static final String KEY_XML = "xml";
    268
    269    /**
    270     * Clears any static resources.
    271     *
    272     * @since 1.5
    273     */
    274    public static void clear() {
    275        ConstantStringLookup.clear();
    276    }
    277
    278    /**
    279     * No need to build instances for now.
    280     */
    281    private StringLookupFactory() {
    282        // empty
    283    }
    284
    285    /**
    286     * Adds the {@link StringLookupFactory default lookups}.
    287     *
    288     * @param stringLookupMap the map of string lookups.
    289     * @since 1.5
    290     */
    291    public void addDefaultStringLookups(final Map<String, StringLookup> stringLookupMap) {
    292        if (stringLookupMap != null) {
    293            // "base64" is deprecated in favor of KEY_BASE64_DECODER.
    294            stringLookupMap.put("base64", Base64DecoderStringLookup.INSTANCE);
    295            for (final DefaultStringLookup stringLookup : DefaultStringLookup.values()) {
    296                stringLookupMap.put(InterpolatorStringLookup.toKey(stringLookup.getKey()),
    297                        stringLookup.getStringLookup());
    298            }
    299        }
    300    }
    301
    302    /**
    303     * Returns the Base64DecoderStringLookup singleton instance to decode Base64 strings.
    304     * <p>
    305     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    306     * </p>
    307     *
    308     * <pre>
    309     * StringLookupFactory.INSTANCE.base64DecoderStringLookup().lookup("SGVsbG9Xb3JsZCE=");
    310     * </pre>
    311     * <p>
    312     * Using a {@link StringSubstitutor}:
    313     * </p>
    314     *
    315     * <pre>
    316     * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ..."));
    317     * </pre>
    318     * <p>
    319     * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
    320     * </p>
    321     *
    322     * @return The DateStringLookup singleton instance.
    323     * @since 1.5
    324     */
    325    public StringLookup base64DecoderStringLookup() {
    326        return Base64DecoderStringLookup.INSTANCE;
    327    }
    328
    329    /**
    330     * Returns the Base64EncoderStringLookup singleton instance to encode strings to Base64.
    331     * <p>
    332     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    333     * </p>
    334     *
    335     * <pre>
    336     * StringLookupFactory.INSTANCE.base64EncoderStringLookup().lookup("HelloWorld!");
    337     * </pre>
    338     * <p>
    339     * Using a {@link StringSubstitutor}:
    340     * </p>
    341     *
    342     * <pre>
    343     * StringSubstitutor.createInterpolator().replace("... ${base64Encoder:HelloWorld!} ..."));
    344     * </pre>
    345     * <p>
    346     * The above examples convert {@code } to {@code "SGVsbG9Xb3JsZCE="}.
    347     * </p>
    348     *
    349     * @return The DateStringLookup singleton instance.
    350     * @since 1.6
    351     */
    352    public StringLookup base64EncoderStringLookup() {
    353        return Base64EncoderStringLookup.INSTANCE;
    354    }
    355
    356    /**
    357     * Returns the Base64DecoderStringLookup singleton instance to decode Base64 strings.
    358     * <p>
    359     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    360     * </p>
    361     *
    362     * <pre>
    363     * StringLookupFactory.INSTANCE.base64DecoderStringLookup().lookup("SGVsbG9Xb3JsZCE=");
    364     * </pre>
    365     * <p>
    366     * Using a {@link StringSubstitutor}:
    367     * </p>
    368     *
    369     * <pre>
    370     * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ..."));
    371     * </pre>
    372     * <p>
    373     * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
    374     * </p>
    375     *
    376     * @return The DateStringLookup singleton instance.
    377     * @since 1.5
    378     * @deprecated Use {@link #base64DecoderStringLookup()}.
    379     */
    380    @Deprecated
    381    public StringLookup base64StringLookup() {
    382        return Base64DecoderStringLookup.INSTANCE;
    383    }
    384
    385    /**
    386     * Returns the ConstantStringLookup singleton instance to look up the value of a fully-qualified static final value.
    387     * <p>
    388     * Sometimes it is necessary in a configuration file to refer to a constant defined in a class. This can be done
    389     * with this lookup implementation. Variable names must be in the format {@code apackage.AClass.AFIELD}. The
    390     * {@code lookup(String)} method will split the passed in string at the last dot, separating the fully qualified
    391     * class name and the name of the constant (i.e. <b>static final</b>) member field. Then the class is loaded and the
    392     * field's value is obtained using reflection.
    393     * </p>
    394     * <p>
    395     * Once retrieved values are cached for fast access. This class is thread-safe. It can be used as a standard (i.e.
    396     * global) lookup object and serve multiple clients concurrently.
    397     * </p>
    398     * <p>
    399     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    400     * </p>
    401     *
    402     * <pre>
    403     * StringLookupFactory.INSTANCE.constantStringLookup().lookup("java.awt.event.KeyEvent.VK_ESCAPE");
    404     * </pre>
    405     * <p>
    406     * Using a {@link StringSubstitutor}:
    407     * </p>
    408     *
    409     * <pre>
    410     * StringSubstitutor.createInterpolator().replace("... ${const:java.awt.event.KeyEvent.VK_ESCAPE} ..."));
    411     * </pre>
    412     * <p>
    413     * The above examples convert {@code java.awt.event.KeyEvent.VK_ESCAPE} to {@code "27"}.
    414     * </p>
    415     *
    416     * @return The DateStringLookup singleton instance.
    417     * @since 1.5
    418     */
    419    public StringLookup constantStringLookup() {
    420        return ConstantStringLookup.INSTANCE;
    421    }
    422
    423    /**
    424     * Returns the DateStringLookup singleton instance to format the current date with the format given in the key in a
    425     * format compatible with {@link java.text.SimpleDateFormat}.
    426     * <p>
    427     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    428     * </p>
    429     *
    430     * <pre>
    431     * StringLookupFactory.INSTANCE.dateStringLookup().lookup("yyyy-MM-dd");
    432     * </pre>
    433     * <p>
    434     * Using a {@link StringSubstitutor}:
    435     * </p>
    436     *
    437     * <pre>
    438     * StringSubstitutor.createInterpolator().replace("... ${date:yyyy-MM-dd} ..."));
    439     * </pre>
    440     * <p>
    441     * The above examples convert {@code "yyyy-MM-dd"} to todays's date, for example, {@code "2019-08-04"}.
    442     * </p>
    443     *
    444     * @return The DateStringLookup singleton instance.
    445     */
    446    public StringLookup dateStringLookup() {
    447        return DateStringLookup.INSTANCE;
    448    }
    449
    450    /**
    451     * Returns the EnvironmentVariableStringLookup singleton instance where the lookup key is an environment variable
    452     * name.
    453     * <p>
    454     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    455     * </p>
    456     *
    457     * <pre>
    458     * StringLookupFactory.INSTANCE.dateStringLookup().lookup("USER");
    459     * </pre>
    460     * <p>
    461     * Using a {@link StringSubstitutor}:
    462     * </p>
    463     *
    464     * <pre>
    465     * StringSubstitutor.createInterpolator().replace("... ${env:USER} ..."));
    466     * </pre>
    467     * <p>
    468     * The above examples convert (on Linux) {@code "USER"} to the current user name. On Windows 10, you would use
    469     * {@code "USERNAME"} to the same effect.
    470     * </p>
    471     *
    472     * @return The EnvironmentVariableStringLookup singleton instance.
    473     */
    474    public StringLookup environmentVariableStringLookup() {
    475        return EnvironmentVariableStringLookup.INSTANCE;
    476    }
    477
    478    /**
    479     * Returns the FileStringLookup singleton instance.
    480     * <p>
    481     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    482     * </p>
    483     *
    484     * <pre>
    485     * StringLookupFactory.INSTANCE.fileStringLookup().lookup("UTF-8:com/domain/document.properties");
    486     * </pre>
    487     * <p>
    488     * Using a {@link StringSubstitutor}:
    489     * </p>
    490     *
    491     * <pre>
    492     * StringSubstitutor.createInterpolator().replace("... ${file:UTF-8:com/domain/document.properties} ..."));
    493     * </pre>
    494     * <p>
    495     * The above examples convert {@code "UTF-8:com/domain/document.properties"} to the contents of the file.
    496     * </p>
    497     *
    498     * @return The FileStringLookup singleton instance.
    499     * @since 1.5
    500     */
    501    public StringLookup fileStringLookup() {
    502        return FileStringLookup.INSTANCE;
    503    }
    504
    505    /**
    506     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
    507     * <p>
    508     * The lookups available to an interpolator are defined in
    509     * </p>
    510     * <p>
    511     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    512     * </p>
    513     *
    514     * <pre>
    515     * StringLookupFactory.INSTANCE.interpolatorStringLookup().lookup("${sys:os.name}, ${env:USER}");
    516     * </pre>
    517     * <p>
    518     * Using a {@link StringSubstitutor}:
    519     * </p>
    520     *
    521     * <pre>
    522     * StringSubstitutor.createInterpolator().replace("... ${sys:os.name}, ${env:USER} ..."));
    523     * </pre>
    524     * <p>
    525     * The above examples convert {@code "${sys:os.name}, ${env:USER}"} to the OS name and Linux user name.
    526     * </p>
    527     *
    528     * @return a new InterpolatorStringLookup.
    529     */
    530    public StringLookup interpolatorStringLookup() {
    531        return InterpolatorStringLookup.INSTANCE;
    532    }
    533
    534    /**
    535     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
    536     * <p>
    537     * If {@code addDefaultLookups} is true, the following lookups are used in addition to the ones provided in
    538     * {@code stringLookupMap}:
    539     * </p>
    540     *
    541     * @param stringLookupMap     the map of string lookups.
    542     * @param defaultStringLookup the default string lookup.
    543     * @param addDefaultLookups   whether to use lookups as described above.
    544     * @return a new InterpolatorStringLookup.
    545     * @since 1.4
    546     */
    547    public StringLookup interpolatorStringLookup(final Map<String, StringLookup> stringLookupMap,
    548            final StringLookup defaultStringLookup, final boolean addDefaultLookups) {
    549        return new InterpolatorStringLookup(stringLookupMap, defaultStringLookup, addDefaultLookups);
    550    }
    551
    552    /**
    553     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
    554     *
    555     * @param <V> the value type the default string lookup's map.
    556     * @param map the default map for string lookups.
    557     * @return a new InterpolatorStringLookup.
    558     */
    559    public <V> StringLookup interpolatorStringLookup(final Map<String, V> map) {
    560        return new InterpolatorStringLookup(map);
    561    }
    562
    563    /**
    564     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
    565     *
    566     * @param defaultStringLookup the default string lookup.
    567     * @return a new InterpolatorStringLookup.
    568     */
    569    public StringLookup interpolatorStringLookup(final StringLookup defaultStringLookup) {
    570        return new InterpolatorStringLookup(defaultStringLookup);
    571    }
    572
    573    /**
    574     * Returns the JavaPlatformStringLookup singleton instance. Looks up keys related to Java: Java version, JRE
    575     * version, VM version, and so on.
    576     * <p>
    577     * The lookup keys with examples are:
    578     * </p>
    579     * <ul>
    580     * <li><b>version</b>: "Java version 1.8.0_181"</li>
    581     * <li><b>runtime</b>: "Java(TM) SE Runtime Environment (build 1.8.0_181-b13) from Oracle Corporation"</li>
    582     * <li><b>vm</b>: "Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)"</li>
    583     * <li><b>os</b>: "Windows 10 10.0, architecture: amd64-64"</li>
    584     * <li><b>hardware</b>: "processors: 4, architecture: amd64-64, instruction sets: amd64"</li>
    585     * <li><b>locale</b>: "default locale: en_US, platform encoding: iso-8859-1"</li>
    586     * </ul>
    587     *
    588     * <p>
    589     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    590     * </p>
    591     *
    592     * <pre>
    593     * StringLookupFactory.INSTANCE.javaPlatformStringLookup().lookup("version");
    594     * </pre>
    595     * <p>
    596     * Using a {@link StringSubstitutor}:
    597     * </p>
    598     *
    599     * <pre>
    600     * StringSubstitutor.createInterpolator().replace("... ${java:version} ..."));
    601     * </pre>
    602     * <p>
    603     * The above examples convert {@code "version"} to the current VM version, for example,
    604     * {@code "Java version 1.8.0_181"}.
    605     * </p>
    606     *
    607     * @return The JavaPlatformStringLookup singleton instance.
    608     */
    609    public StringLookup javaPlatformStringLookup() {
    610        return JavaPlatformStringLookup.INSTANCE;
    611    }
    612
    613    /**
    614     * Returns the LocalHostStringLookup singleton instance where the lookup key is one of:
    615     * <ul>
    616     * <li><b>name</b>: for the local host name, for example {@code EXAMPLE}.</li>
    617     * <li><b>canonical-name</b>: for the local canonical host name, for example {@code EXAMPLE.apache.org}.</li>
    618     * <li><b>address</b>: for the local host address, for example {@code 192.168.56.1}.</li>
    619     * </ul>
    620     *
    621     * <p>
    622     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    623     * </p>
    624     *
    625     * <pre>
    626     * StringLookupFactory.INSTANCE.localHostStringLookup().lookup("canonical-name");
    627     * </pre>
    628     * <p>
    629     * Using a {@link StringSubstitutor}:
    630     * </p>
    631     *
    632     * <pre>
    633     * StringSubstitutor.createInterpolator().replace("... ${localhost:canonical-name} ..."));
    634     * </pre>
    635     * <p>
    636     * The above examples convert {@code "canonical-name"} to the current host name, for example,
    637     * {@code "EXAMPLE.apache.org"}.
    638     * </p>
    639     *
    640     * @return The DateStringLookup singleton instance.
    641     */
    642    public StringLookup localHostStringLookup() {
    643        return LocalHostStringLookup.INSTANCE;
    644    }
    645
    646    /**
    647     * Returns the DnsStringLookup singleton instance where the lookup key is one of:
    648     * <ul>
    649     * <li><b>name</b>: for the local host name, for example {@code EXAMPLE} but also {@code EXAMPLE.apache.org}.</li>
    650     * <li><b>canonical-name</b>: for the local canonical host name, for example {@code EXAMPLE.apache.org}.</li>
    651     * <li><b>address</b>: for the local host address, for example {@code 192.168.56.1}.</li>
    652     * </ul>
    653     *
    654     * <p>
    655     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    656     * </p>
    657     *
    658     * <pre>
    659     * StringLookupFactory.INSTANCE.dnsStringLookup().lookup("address|apache.org");
    660     * </pre>
    661     * <p>
    662     * Using a {@link StringSubstitutor}:
    663     * </p>
    664     *
    665     * <pre>
    666     * StringSubstitutor.createInterpolator().replace("... ${dns:address|apache.org} ..."));
    667     * </pre>
    668     * <p>
    669     * The above examples convert {@code "address|apache.org"} to {@code "95.216.24.32} (or {@code "40.79.78.1"}).
    670     * </p>
    671     *
    672     * @return the DateStringLookup singleton instance.
    673     * @since 1.8
    674     */
    675    public StringLookup dnsStringLookup() {
    676        return DnsStringLookup.INSTANCE;
    677    }
    678
    679    /**
    680     * Returns a new map-based lookup where the request for a lookup is answered with the value for that key.
    681     *
    682     * @param <V> the map value type.
    683     * @param map the map.
    684     * @return a new MapStringLookup.
    685     */
    686    public <V> StringLookup mapStringLookup(final Map<String, V> map) {
    687        return MapStringLookup.on(map);
    688    }
    689
    690    /**
    691     * Returns the NullStringLookup singleton instance which always returns null.
    692     *
    693     * @return The NullStringLookup singleton instance.
    694     */
    695    public StringLookup nullStringLookup() {
    696        return NullStringLookup.INSTANCE;
    697    }
    698
    699    /**
    700     * Returns the PropertiesStringLookup singleton instance.
    701     * <p>
    702     * Looks up the value for the key in the format "DocumentPath::MyKey".
    703     * </p>
    704     * <p>
    705     * Note the use of "::" instead of ":" to allow for "C:" drive letters in paths.
    706     * </p>
    707     * <p>
    708     * For example: "com/domain/document.properties::MyKey".
    709     * </p>
    710     *
    711     * <p>
    712     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    713     * </p>
    714     *
    715     * <pre>
    716     * StringLookupFactory.INSTANCE.propertiesStringLookup().lookup("com/domain/document.properties::MyKey");
    717     * </pre>
    718     * <p>
    719     * Using a {@link StringSubstitutor}:
    720     * </p>
    721     *
    722     * <pre>
    723     * StringSubstitutor.createInterpolator().replace("... ${properties:com/domain/document.properties::MyKey} ..."));
    724     * </pre>
    725     * <p>
    726     * The above examples convert {@code "com/domain/document.properties::MyKey"} to the key value in the properties
    727     * file at the path "com/domain/document.properties".
    728     * </p>
    729     *
    730     * @return The PropertiesStringLookup singleton instance.
    731     * @since 1.5
    732     */
    733    public StringLookup propertiesStringLookup() {
    734        return PropertiesStringLookup.INSTANCE;
    735    }
    736
    737    /**
    738     * Returns the ResourceBundleStringLookup singleton instance.
    739     * <p>
    740     * Looks up the value for a given key in the format "BundleName:BundleKey".
    741     * </p>
    742     * <p>
    743     * For example: "com.domain.messages:MyKey".
    744     * </p>
    745     * <p>
    746     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    747     * </p>
    748     *
    749     * <pre>
    750     * StringLookupFactory.INSTANCE.resourceBundleStringLookup().lookup("com.domain.messages:MyKey");
    751     * </pre>
    752     * <p>
    753     * Using a {@link StringSubstitutor}:
    754     * </p>
    755     *
    756     * <pre>
    757     * StringSubstitutor.createInterpolator().replace("... ${resourceBundle:com.domain.messages:MyKey} ..."));
    758     * </pre>
    759     * <p>
    760     * The above examples convert {@code "com.domain.messages:MyKey"} to the key value in the resource bundle at
    761     * {@code "com.domain.messages"}.
    762     * </p>
    763     *
    764     * @return The ResourceBundleStringLookup singleton instance.
    765     */
    766    public StringLookup resourceBundleStringLookup() {
    767        return ResourceBundleStringLookup.INSTANCE;
    768    }
    769
    770    /**
    771     * Returns a ResourceBundleStringLookup instance for the given bundle name.
    772     * <p>
    773     * Looks up the value for a given key in the format "MyKey".
    774     * </p>
    775     * <p>
    776     * For example: "MyKey".
    777     * </p>
    778     * <p>
    779     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    780     * </p>
    781     *
    782     * <pre>
    783     * StringLookupFactory.INSTANCE.resourceBundleStringLookup("com.domain.messages").lookup("MyKey");
    784     * </pre>
    785     * <p>
    786     * The above example converts {@code "MyKey"} to the key value in the resource bundle at
    787     * {@code "com.domain.messages"}.
    788     * </p>
    789     *
    790     * @param bundleName Only lookup in this bundle.
    791     * @return a ResourceBundleStringLookup instance for the given bundle name.
    792     * @since 1.5
    793     */
    794    public StringLookup resourceBundleStringLookup(final String bundleName) {
    795        return new ResourceBundleStringLookup(bundleName);
    796    }
    797
    798    /**
    799     * Returns the ScriptStringLookup singleton instance.
    800     * <p>
    801     * Looks up the value for the key in the format "ScriptEngineName:Script".
    802     * </p>
    803     * <p>
    804     * For example: "javascript:3 + 4".
    805     * </p>
    806     * <p>
    807     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    808     * </p>
    809     *
    810     * <pre>
    811     * StringLookupFactory.INSTANCE.scriptStringLookup().lookup("javascript:3 + 4");
    812     * </pre>
    813     * <p>
    814     * Using a {@link StringSubstitutor}:
    815     * </p>
    816     *
    817     * <pre>
    818     * StringSubstitutor.createInterpolator().replace("... ${javascript:3 + 4} ..."));
    819     * </pre>
    820     * <p>
    821     * The above examples convert {@code "javascript:3 + 4"} to {@code "7"}.
    822     * </p>
    823     *
    824     * @return The ScriptStringLookup singleton instance.
    825     * @since 1.5
    826     */
    827    public StringLookup scriptStringLookup() {
    828        return ScriptStringLookup.INSTANCE;
    829    }
    830
    831    /**
    832     * Returns the SystemPropertyStringLookup singleton instance where the lookup key is a system property name.
    833     *
    834     * <p>
    835     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    836     * </p>
    837     *
    838     * <pre>
    839     * StringLookupFactory.INSTANCE.systemPropertyStringLookup().lookup("os.name");
    840     * </pre>
    841     * <p>
    842     * Using a {@link StringSubstitutor}:
    843     * </p>
    844     *
    845     * <pre>
    846     * StringSubstitutor.createInterpolator().replace("... ${sys:os.name} ..."));
    847     * </pre>
    848     * <p>
    849     * The above examples convert {@code "os.name"} to the operating system name.
    850     * </p>
    851     *
    852     * @return The SystemPropertyStringLookup singleton instance.
    853     */
    854    public StringLookup systemPropertyStringLookup() {
    855        return SystemPropertyStringLookup.INSTANCE;
    856    }
    857
    858    /**
    859     * Returns the UrlDecoderStringLookup singleton instance.
    860     * <p>
    861     * Decodes URL Strings using the UTF-8 encoding.
    862     * </p>
    863     * <p>
    864     * For example: "Hello%20World%21" becomes "Hello World!".
    865     * </p>
    866     * <p>
    867     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    868     * </p>
    869     *
    870     * <pre>
    871     * StringLookupFactory.INSTANCE.urlDecoderStringLookup().lookup("Hello%20World%21");
    872     * </pre>
    873     * <p>
    874     * Using a {@link StringSubstitutor}:
    875     * </p>
    876     *
    877     * <pre>
    878     * StringSubstitutor.createInterpolator().replace("... ${urlDecoder:Hello%20World%21} ..."));
    879     * </pre>
    880     * <p>
    881     * The above examples convert {@code "Hello%20World%21"} to {@code "Hello World!"}.
    882     * </p>
    883     *
    884     * @return The UrlStringLookup singleton instance.
    885     * @since 1.6
    886     */
    887    public StringLookup urlDecoderStringLookup() {
    888        return UrlDecoderStringLookup.INSTANCE;
    889    }
    890
    891    /**
    892     * Returns the UrlDecoderStringLookup singleton instance.
    893     * <p>
    894     * Decodes URL Strings using the UTF-8 encoding.
    895     * </p>
    896     * <p>
    897     * For example: "Hello World!" becomes "Hello+World%21".
    898     * </p>
    899     * <p>
    900     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    901     * </p>
    902     *
    903     * <pre>
    904     * StringLookupFactory.INSTANCE.urlEncoderStringLookup().lookup("Hello World!");
    905     * </pre>
    906     * <p>
    907     * Using a {@link StringSubstitutor}:
    908     * </p>
    909     *
    910     * <pre>
    911     * StringSubstitutor.createInterpolator().replace("... ${urlEncoder:Hello World!} ..."));
    912     * </pre>
    913     * <p>
    914     * The above examples convert {@code "Hello World!"} to {@code "Hello%20World%21"}.
    915     * </p>
    916     *
    917     * @return The UrlStringLookup singleton instance.
    918     * @since 1.6
    919     */
    920    public StringLookup urlEncoderStringLookup() {
    921        return UrlEncoderStringLookup.INSTANCE;
    922    }
    923
    924    /**
    925     * Returns the UrlStringLookup singleton instance.
    926     * <p>
    927     * Looks up the value for the key in the format "CharsetName:URL".
    928     * </p>
    929     * <p>
    930     * For example, using the HTTP scheme: "UTF-8:http://www.google.com"
    931     * </p>
    932     * <p>
    933     * For example, using the file scheme:
    934     * "UTF-8:file:///C:/somehome/commons/commons-text/src/test/resources/document.properties"
    935     * </p>
    936     * <p>
    937     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    938     * </p>
    939     *
    940     * <pre>
    941     * StringLookupFactory.INSTANCE.urlStringLookup().lookup("UTF-8:https://www.apache.org");
    942     * </pre>
    943     * <p>
    944     * Using a {@link StringSubstitutor}:
    945     * </p>
    946     *
    947     * <pre>
    948     * StringSubstitutor.createInterpolator().replace("... ${url:UTF-8:https://www.apache.org} ..."));
    949     * </pre>
    950     * <p>
    951     * The above examples convert {@code "UTF-8:https://www.apache.org"} to the contents of that page.
    952     * </p>
    953     *
    954     * @return The UrlStringLookup singleton instance.
    955     * @since 1.5
    956     */
    957    public StringLookup urlStringLookup() {
    958        return UrlStringLookup.INSTANCE;
    959    }
    960
    961    /**
    962     * Returns the XmlStringLookup singleton instance.
    963     * <p>
    964     * Looks up the value for the key in the format "DocumentPath:XPath".
    965     * </p>
    966     * <p>
    967     * For example: "com/domain/document.xml:/path/to/node".
    968     * </p>
    969     * <p>
    970     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
    971     * </p>
    972     *
    973     * <pre>
    974     * StringLookupFactory.INSTANCE.xmlStringLookup().lookup("com/domain/document.xml:/path/to/node");
    975     * </pre>
    976     * <p>
    977     * Using a {@link StringSubstitutor}:
    978     * </p>
    979     *
    980     * <pre>
    981     * StringSubstitutor.createInterpolator().replace("... ${xml:com/domain/document.xml:/path/to/node} ..."));
    982     * </pre>
    983     * <p>
    984     * The above examples convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML
    985     * document.
    986     * </p>
    987     *
    988     * @return The XmlStringLookup singleton instance.
    989     * @since 1.5
    990     */
    991    public StringLookup xmlStringLookup() {
    992        return XmlStringLookup.INSTANCE;
    993    }
    994
    995}