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 }