1 | |
package org.kuali.spring.util; |
2 | |
|
3 | |
import java.util.ArrayList; |
4 | |
import java.util.Collections; |
5 | |
import java.util.List; |
6 | |
import java.util.Properties; |
7 | |
|
8 | |
import org.slf4j.Logger; |
9 | |
import org.slf4j.LoggerFactory; |
10 | |
import org.springframework.util.ObjectUtils; |
11 | |
|
12 | 8 | public class PropertiesResolver extends PlaceholderStringResolver { |
13 | 1 | private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesResolver.class); |
14 | |
public static final boolean DEFAULT_IS_SORT = true; |
15 | 8 | boolean sort = DEFAULT_IS_SORT; |
16 | |
|
17 | 8 | protected class ResolvePropertyContext { |
18 | |
public ResolvePropertyContext(List<String> keys, String key, Properties properties, |
19 | 441 | Properties resolvedProperties, ValueRetriever retriever) { |
20 | 441 | super(); |
21 | 441 | this.keys = keys; |
22 | 441 | this.key = key; |
23 | 441 | this.properties = properties; |
24 | 441 | this.resolvedProperties = resolvedProperties; |
25 | 441 | this.retriever = retriever; |
26 | 441 | } |
27 | |
|
28 | |
List<String> keys; |
29 | |
String key; |
30 | |
Properties properties; |
31 | |
Properties resolvedProperties; |
32 | |
ValueRetriever retriever; |
33 | |
|
34 | |
public List<String> getKeys() { |
35 | 0 | return keys; |
36 | |
} |
37 | |
|
38 | |
public void setKeys(List<String> keys) { |
39 | 0 | this.keys = keys; |
40 | 0 | } |
41 | |
|
42 | |
public String getKey() { |
43 | 882 | return key; |
44 | |
} |
45 | |
|
46 | |
public void setKey(String key) { |
47 | 0 | this.key = key; |
48 | 0 | } |
49 | |
|
50 | |
public Properties getProperties() { |
51 | 882 | return properties; |
52 | |
} |
53 | |
|
54 | |
public void setProperties(Properties properties) { |
55 | 0 | this.properties = properties; |
56 | 0 | } |
57 | |
|
58 | |
public Properties getResolvedProperties() { |
59 | 441 | return resolvedProperties; |
60 | |
} |
61 | |
|
62 | |
public void setResolvedProperties(Properties resolvedProperties) { |
63 | 0 | this.resolvedProperties = resolvedProperties; |
64 | 0 | } |
65 | |
|
66 | |
public ValueRetriever getRetriever() { |
67 | 882 | return retriever; |
68 | |
} |
69 | |
|
70 | |
public void setRetriever(ValueRetriever retriever) { |
71 | 0 | this.retriever = retriever; |
72 | 0 | } |
73 | |
} |
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
public Properties resolve(Properties properties) { |
79 | 4 | return resolve(properties, new PropertiesRetriever(properties)); |
80 | |
} |
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
public Properties resolve(Properties properties, ValueRetriever retriever) { |
87 | |
|
88 | 4 | Properties resolvedProperties = new Properties(); |
89 | |
|
90 | 4 | List<String> keys = new ArrayList<String>(properties.stringPropertyNames()); |
91 | 4 | if (isSort()) { |
92 | |
|
93 | 4 | Collections.sort(keys); |
94 | |
} |
95 | |
|
96 | 4 | for (String key : keys) { |
97 | 441 | resolveProperty(new ResolvePropertyContext(keys, key, properties, resolvedProperties, retriever)); |
98 | |
} |
99 | 4 | return resolvedProperties; |
100 | |
} |
101 | |
|
102 | |
protected void resolveProperty(ResolvePropertyContext ctx) { |
103 | 441 | String key = ctx.getKey(); |
104 | 441 | Properties properties = ctx.getProperties(); |
105 | |
|
106 | 441 | String resolvedKey = resolve(key, ctx.getRetriever()); |
107 | |
|
108 | |
|
109 | 441 | if (!key.equals(resolvedKey)) { |
110 | 0 | LOGGER.info("Resolved key [{}]->[{}]", key, resolvedKey); |
111 | |
} |
112 | |
|
113 | |
|
114 | 441 | String value = properties.getProperty(key); |
115 | |
|
116 | 441 | String resolvedValue = resolve(value, ctx.getRetriever()); |
117 | |
|
118 | |
|
119 | 441 | duplicatePropertyCheck(ctx, resolvedKey, resolvedValue); |
120 | |
|
121 | |
|
122 | 441 | if (!value.equals(resolvedValue)) { |
123 | 1 | LOGGER.info("Resolved value for '" + resolvedKey + "' [{}]->[{}]", |
124 | |
plogger.getLogValue(resolvedKey, value), plogger.getLogValue(resolvedKey, resolvedValue)); |
125 | |
} |
126 | 441 | LOGGER.debug("Adding resolved property {}=[{}]", resolvedKey, plogger.getLogValue(resolvedKey, resolvedValue)); |
127 | |
|
128 | 441 | ctx.getResolvedProperties().setProperty(resolvedKey, resolvedValue); |
129 | 441 | } |
130 | |
|
131 | |
|
132 | |
|
133 | |
|
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
|
142 | |
|
143 | |
protected void duplicatePropertyCheck(ResolvePropertyContext ctx, String resolvedKey, String resolvedValue) { |
144 | 441 | String rawKey = ctx.getKey(); |
145 | 441 | Properties properties = ctx.getProperties(); |
146 | |
|
147 | 441 | if (rawKey.equals(resolvedKey)) { |
148 | 441 | return; |
149 | |
} |
150 | |
|
151 | |
|
152 | 0 | if (!ctx.getKeys().contains(resolvedKey)) { |
153 | 0 | return; |
154 | |
} |
155 | |
|
156 | |
|
157 | |
|
158 | |
|
159 | 0 | String existingValue = properties.getProperty(resolvedKey); |
160 | |
|
161 | |
|
162 | 0 | if (ObjectUtils.nullSafeEquals(existingValue, resolvedValue)) { |
163 | |
|
164 | 0 | LOGGER.warn("Duplicate property detected for '" + resolvedKey + "'. '" + rawKey + "' resolved to '" |
165 | |
+ resolvedKey + "' which already has a value. Both values are the same: [{}]", |
166 | |
plogger.getLogValue(resolvedKey, existingValue)); |
167 | 0 | return; |
168 | |
} else { |
169 | |
|
170 | 0 | StringBuilder sb = new StringBuilder(); |
171 | 0 | sb.append("Duplicate property value detected for '" + resolvedKey + "'."); |
172 | 0 | sb.append(" The key '" + rawKey + "' resolved to '" + resolvedKey |
173 | |
+ "' and there is a value for that key already present."); |
174 | 0 | sb.append(" Existing value:[" + existingValue + "] New Value:[" + resolvedValue + "]"); |
175 | 0 | throw new IllegalArgumentException(sb.toString()); |
176 | |
} |
177 | |
} |
178 | |
|
179 | |
public boolean isSort() { |
180 | 5 | return sort; |
181 | |
} |
182 | |
|
183 | |
public void setSort(boolean sort) { |
184 | 1 | this.sort = sort; |
185 | 1 | } |
186 | |
|
187 | |
} |