View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  
18  package org.apache.commons.text.lookup;
19  
20  import java.io.InputStream;
21  import java.nio.file.Files;
22  import java.nio.file.Path;
23  import java.util.Properties;
24  
25  import org.apache.commons.lang3.StringUtils;
26  
27  /**
28   * Looks up keys from a properties file.
29   * <p>
30   * Looks up the value for a given key in the format "Document::Key".
31   * </p>
32   * <p>
33   * Note the use of "::" instead of ":" to allow for "C:" drive letters in paths.
34   * </p>
35   * <p>
36   * For example: "com/domain/document.properties:key".
37   * </p>
38   * <p>
39   * Public access is through {@link StringLookupFactory}.
40   * </p>
41   *
42   * @see StringLookupFactory
43   * @see Properties
44   * @since 1.5
45   */
46  final class PropertiesStringLookup extends AbstractPathFencedLookup {
47  
48      /**
49       * Defines the singleton for this class.
50       */
51      static final PropertiesStringLookup INSTANCE = new PropertiesStringLookup((Path[]) null);
52  
53      /** Separates file and key. */
54      static final String SEPARATOR = "::";
55  
56      /**
57       * Creates a lookup key for a given file and key.
58       */
59      static String toPropertyKey(final String file, final String key) {
60          return toLookupKey(file, SEPARATOR, key);
61      }
62  
63      /**
64       * Constructs a new instance.
65       *
66       * @param fences The fences guarding Path resolution.
67       */
68      PropertiesStringLookup(final Path... fences) {
69          super(fences);
70      }
71  
72      /**
73       * Looks up the value for the key in the format "DocumentPath:XPath".
74       * <p>
75       * For example: "com/domain/document.xml::/path/to/node".
76       * </p>
77       * <p>
78       * Note the use of "::" instead of ":" to allow for "C:" drive letters in paths.
79       * </p>
80       *
81       * @param key the key to be looked up, may be null.
82       * @return The value associated with the key.
83       */
84      @Override
85      public String lookup(final String key) {
86          if (key == null) {
87              return null;
88          }
89          final String[] keys = key.split(SEPARATOR);
90          final int keyLen = keys.length;
91          if (keyLen < 2) {
92              throw IllegalArgumentExceptions.format("Bad properties key format [%s]; expected format is %s.", key,
93                  toPropertyKey("DocumentPath", "Key"));
94          }
95          final String documentPath = keys[0];
96          final String propertyKey = StringUtils.substringAfter(key, SEPARATOR);
97          try {
98              final Properties properties = new Properties();
99              try (InputStream inputStream = Files.newInputStream(getPath(documentPath))) {
100                 properties.load(inputStream);
101             }
102             return properties.getProperty(propertyKey);
103         } catch (final Exception e) {
104             throw IllegalArgumentExceptions.format(e, "Error looking up properties [%s] and key [%s].", documentPath,
105                 propertyKey);
106         }
107     }
108 
109 }