1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.spi.config.support;
17
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.Iterator;
21 import java.util.LinkedHashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Properties;
25
26 import org.apache.commons.lang.ObjectUtils;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 import de.smartics.properties.api.config.domain.ConfigurationException;
31 import de.smartics.properties.api.config.domain.DuplicatePropertyException;
32 import de.smartics.properties.api.config.domain.Property;
33 import de.smartics.properties.api.config.domain.PropertyLocation;
34 import de.smartics.properties.api.config.domain.PropertyProvider;
35 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
36
37
38
39
40 class MultiSourceProperties
41 {
42
43
44
45
46
47
48
49 private static final Logger LOG = LoggerFactory
50 .getLogger(MultiSourceProperties.class);
51
52
53
54
55
56
57 private final ConfigurationKey configurationKey;
58
59
60
61
62
63 private final List<ConfigurationException> exceptions;
64
65
66
67
68 private final Map<PropertyLocation, PropertyProvider> propertiesMap =
69 new LinkedHashMap<PropertyLocation, PropertyProvider>();
70
71
72
73
74
75
76
77
78
79
80
81
82 MultiSourceProperties(final ConfigurationKey configurationKey,
83 final List<ConfigurationException> exceptions)
84 {
85 this.configurationKey = configurationKey;
86 this.exceptions = exceptions;
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 public ConfigurationKey getConfigurationKey()
103 {
104 return configurationKey;
105 }
106
107
108
109
110
111
112
113 public List<ConfigurationException> getExceptions()
114 {
115 if (exceptions != null)
116 {
117 return exceptions;
118 }
119 else
120 {
121 return Collections.emptyList();
122 }
123 }
124
125
126
127 void add(final PropertyLocation source, final Properties properties)
128 {
129 if (propertiesMap.containsKey(source))
130 {
131 LOG.warn("Properties from '{}' already added.", source);
132 return;
133 }
134
135 for (final Iterator<Object> i = properties.keySet().iterator(); i.hasNext();)
136 {
137 final Object key = i.next();
138 final Object value = properties.get(key);
139 if (contains(source, key, value))
140 {
141 LOG.info("Duplicate property '{}' of '{}' removed.", key, source);
142 i.remove();
143 }
144 }
145
146 final PropertiesPropertyProvider provider =
147 new PropertiesPropertyProvider(configurationKey, source, properties);
148 propertiesMap.put(source, provider);
149 }
150
151 void addProviders(final Collection<PropertyProvider> providers)
152 {
153 for (final PropertyProvider provider : providers)
154 {
155 addProvider(provider);
156 }
157 }
158
159 void addProvider(final PropertyProvider provider)
160 {
161 final PropertyLocation source = provider.getSourceId();
162 if (propertiesMap.containsKey(source))
163 {
164 LOG.warn("Properties from '{}' already added.", source);
165 return;
166 }
167
168 propertiesMap.put(source, provider);
169 }
170
171 private boolean contains(final PropertyLocation newSource, final Object key,
172 final Object newValue)
173 {
174 boolean contains = false;
175 for (final Map.Entry<PropertyLocation, PropertyProvider> entry : propertiesMap
176 .entrySet())
177 {
178 final PropertyLocation currentSource = entry.getKey();
179 final PropertyProvider currentProperties = entry.getValue();
180
181 final String name = ObjectUtils.toString(key, null);
182 if (currentProperties.containsKey(name))
183 {
184 final Property property = currentProperties.getProperty(name);
185 final String currentValue =
186 property != null ? property.getValue() : null;
187 final String currentValueString =
188 ObjectUtils.toString(currentValue, null);
189 final String newValueString = ObjectUtils.toString(newValue, null);
190 if (!ObjectUtils.equals(currentValueString, newValueString))
191 {
192 if (exceptions != null)
193 {
194 addException(newSource, currentSource, name, currentValueString,
195 newValueString);
196 }
197 else
198 {
199 warnDuplicateWithDifferentValue(newSource, newValue, currentSource,
200 name, currentValue);
201 }
202 }
203 else
204 {
205 warnDuplicateWithSameValue(newValue, currentSource, name,
206 currentValue);
207 }
208
209 contains = true;
210 }
211 }
212
213 return contains;
214 }
215
216 private void addException(final PropertyLocation newSource,
217 final PropertyLocation currentSource, final String name,
218 final String currentValueString, final String newValueString)
219 {
220 final DuplicatePropertyException e =
221 new DuplicatePropertyException(configurationKey,
222 new Property(currentSource, ObjectUtils.toString(name, null),
223 currentValueString), new Property(newSource,
224 ObjectUtils.toString(name, null), newValueString));
225 exceptions.add(e);
226 }
227
228 private void warnDuplicateWithDifferentValue(
229 final PropertyLocation newSource, final Object newValue,
230 final PropertyLocation currentSource, final String name,
231 final String currentValue)
232 {
233 LOG.warn("Duplicate key '{}' with new value '{}' in\n '{}'."
234 + "\nAlready found in\n '{}'\nwith value '{}' (active).",
235 new Object[] { name, newValue, newSource, currentSource, currentValue });
236 }
237
238 private void warnDuplicateWithSameValue(final Object newValue,
239 final PropertyLocation currentSource, final String name,
240 final String currentValue)
241 {
242 LOG.warn("Duplicate key '{}' with same value '{}' in\n '{}'\n and in\n."
243 + " '{}'.", new Object[] { name, newValue, currentValue,
244 currentSource });
245 }
246
247 Property getValue(final String key)
248 {
249 for (final Map.Entry<PropertyLocation, PropertyProvider> entry : propertiesMap
250 .entrySet())
251 {
252 final PropertyProvider currentProperties = entry.getValue();
253
254 if (currentProperties.containsKey(key))
255 {
256 final Property property = currentProperties.getProperty(key);
257 return property;
258 }
259 }
260
261 return null;
262 }
263
264
265
266
267
268
269
270
271 @Override
272 public String toString()
273 {
274 final StringBuilder buffer = new StringBuilder();
275
276 buffer.append(configurationKey).append('=');
277
278 for (final PropertyLocation source : propertiesMap.keySet())
279 {
280 buffer.append(' ').append(source);
281 }
282
283 if (exceptions != null)
284 {
285 buffer.append("Exceptions:");
286 for (final Exception e : exceptions)
287 {
288 buffer.append('\n').append(e.getMessage());
289 }
290 }
291
292 return buffer.toString();
293 }
294 }