1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package ch.elca.el4j.core.config;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Enumeration;
25 import java.util.List;
26 import java.util.Properties;
27
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.springframework.beans.BeanWrapperImpl;
31 import org.springframework.beans.MutablePropertyValues;
32 import org.springframework.beans.PropertyValue;
33 import org.springframework.beans.factory.config.BeanDefinition;
34 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
35 import org.springframework.beans.factory.config.PropertyOverrideConfigurer;
36 import org.springframework.beans.factory.config.TypedStringValue;
37 import org.springframework.beans.factory.support.ManagedList;
38 import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
39 import org.springframework.core.io.Resource;
40 import org.springframework.util.DefaultPropertiesPersister;
41 import org.springframework.util.PropertiesPersister;
42
43 import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class ListPropertyMergeConfigurer extends PropertyOverrideConfigurer {
70
71
72
73 private static Logger s_logger
74 = LoggerFactory.getLogger(ListPropertyMergeConfigurer.class);
75
76
77
78
79 private Properties m_properties;
80
81
82
83
84 private Resource[] m_locations;
85
86
87
88
89 private String m_fileEncoding;
90
91
92
93
94 private PropertiesPersister m_propertiesPersister
95 = new DefaultPropertiesPersister();
96
97
98
99
100 private boolean m_ignoreResourceNotFound = false;
101
102
103
104
105 private boolean m_insertNewItemsAfter = true;
106
107
108
109
110 public final void setProperties(Properties properties) {
111 m_properties = properties;
112 }
113
114
115
116
117 public final void setLocation(Resource location) {
118 m_locations = new Resource[] {location};
119 super.setLocation(location);
120 }
121
122
123
124
125 public final void setLocations(Resource[] locations) {
126 super.setLocations(locations);
127 m_locations = locations;
128 }
129
130
131
132
133 public final void setFileEncoding(String encoding) {
134 super.setFileEncoding(encoding);
135 m_fileEncoding = encoding;
136 }
137
138
139
140
141 public final void setPropertiesPersister(
142 PropertiesPersister propertiesPersister) {
143 super.setPropertiesPersister(propertiesPersister);
144 m_propertiesPersister = propertiesPersister;
145 }
146
147
148
149
150 public final void setIgnoreResourceNotFound(
151 boolean ignoreResourceNotFound) {
152 super.setIgnoreResourceNotFound(ignoreResourceNotFound);
153 m_ignoreResourceNotFound = ignoreResourceNotFound;
154 }
155
156
157
158
159 public final String getFileEncoding() {
160 return m_fileEncoding;
161 }
162
163
164
165
166 public final boolean isIgnoreResourceNotFound() {
167 return m_ignoreResourceNotFound;
168 }
169
170
171
172
173 public final Resource[] getLocations() {
174 return m_locations.clone();
175 }
176
177
178
179
180 public final Properties getProperties() {
181 return m_properties;
182 }
183
184
185
186
187 public final PropertiesPersister getPropertiesPersister() {
188 return m_propertiesPersister;
189 }
190
191
192
193
194
195
196 public final boolean isInsertNewItemsAfter() {
197 return m_insertNewItemsAfter;
198 }
199
200
201
202
203
204
205 public final void setInsertNewItemsAfter(boolean insertNewItemsAfter) {
206 m_insertNewItemsAfter = insertNewItemsAfter;
207 }
208
209
210
211
212
213
214
215
216 public final boolean isInsertNewItemsBefore() {
217 return !isInsertNewItemsAfter();
218 }
219
220
221
222
223
224
225
226
227 public final void setInsertNewItemsBefore(boolean insertNewItemsBefore) {
228 setInsertNewItemsAfter(!insertNewItemsBefore);
229 }
230
231
232
233
234 @Override
235 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
236 Properties mergedProps = new Properties();
237
238 addDefaultProperties(mergedProps);
239
240 Resource[] locations = getLocations();
241 if (locations != null) {
242 for (int i = 0; i < locations.length; i++) {
243 Resource location = locations[i];
244 loadProperties(mergedProps, location);
245 processProperties(beanFactory, mergedProps);
246 mergedProps = new Properties();
247 }
248 } else {
249 processProperties(beanFactory, mergedProps);
250 }
251 }
252
253
254
255
256
257
258 protected void addDefaultProperties(Properties mergedProps) {
259 Properties defaultProperties = getProperties();
260 if (defaultProperties != null) {
261
262 Enumeration en = defaultProperties.propertyNames();
263 while (en.hasMoreElements()) {
264 String key = (String) en.nextElement();
265 mergedProps.setProperty(
266 key, defaultProperties.getProperty(key));
267 }
268 }
269 }
270
271
272
273
274
275
276
277 protected void loadProperties(Properties mergedProps, Resource location) {
278 if (logger.isInfoEnabled()) {
279 logger.info("Loading properties file from " + location);
280 }
281 InputStream is = null;
282 try {
283 is = location.getInputStream();
284 if (location.getFilename().endsWith(XML_FILE_EXTENSION)) {
285 getPropertiesPersister().loadFromXml(mergedProps, is);
286 } else {
287 String fileEncoding = getFileEncoding();
288 if (fileEncoding != null) {
289 getPropertiesPersister().load(mergedProps,
290 new InputStreamReader(is, fileEncoding));
291 } else {
292 getPropertiesPersister().load(mergedProps, is);
293 }
294 }
295 } catch (IOException ex) {
296 String msg = "Could not load properties from " + location;
297 if (isIgnoreResourceNotFound()) {
298 if (s_logger.isWarnEnabled()) {
299 s_logger.warn(msg + ": " + ex.getMessage());
300 }
301 } else {
302 CoreNotificationHelper.notifyMisconfiguration(msg, ex);
303 }
304 } finally {
305 if (is != null) {
306 try {
307 is.close();
308 } catch (IOException e) {
309 if (s_logger.isWarnEnabled()) {
310 s_logger.warn("Inputstream could not be "
311 + "properly closed.", e);
312 }
313 }
314 }
315 }
316 }
317
318
319
320
321 @Override
322 protected void applyPropertyValue(ConfigurableListableBeanFactory factory,
323 String beanName, String property, String value) {
324
325
326
327 BeanWrapperImpl beanWrapper = new BeanWrapperImpl();
328 beanWrapper.registerCustomEditor(String[].class, new
329 StringArrayPropertyEditor());
330 BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);
331 MutablePropertyValues mutablePropertyValues = beanDefinition
332 .getPropertyValues();
333 PropertyValue propertyValue = mutablePropertyValues
334 .getPropertyValue(property);
335
336
337
338
339 List oldValueList = new ArrayList();
340 if (propertyValue != null) {
341 Object valueObject = propertyValue.getValue();
342 if (valueObject instanceof Collection) {
343 oldValueList.addAll((Collection) valueObject);
344 } else {
345
346 String[] oldValues = (String[]) beanWrapper.convertIfNecessary(
347 valueObject, String[].class);
348
349
350
351 for (int i = 0; i < oldValues.length; i++) {
352 String oldValue = oldValues[i];
353 oldValueList.add(oldValue != null ? oldValue.trim()
354 : oldValue);
355 }
356 }
357 }
358
359
360
361
362 List newValueList = new ArrayList();
363 String[] newValues = (String[]) beanWrapper.convertIfNecessary(value,
364 String[].class);
365
366
367 for (int i = 0; i < newValues.length; i++) {
368 String newValue = newValues[i];
369 TypedStringValue typedValue = null;
370 if (newValue != null) {
371 newValue = newValue.trim();
372 typedValue = new TypedStringValue(newValue);
373 }
374 newValueList.add(typedValue);
375 }
376
377
378
379
380 ManagedList mixedValueList = new ManagedList();
381 if (isInsertNewItemsAfter()) {
382 mixedValueList.addAll(oldValueList);
383 mixedValueList.addAll(newValueList);
384 } else {
385 mixedValueList.addAll(newValueList);
386 mixedValueList.addAll(oldValueList);
387 }
388 mutablePropertyValues.addPropertyValue(property, mixedValueList);
389 }
390 }