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