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.beans.PropertyChangeListener;
19 import java.beans.PropertyChangeSupport;
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22
23 import javax.annotation.concurrent.ThreadSafe;
24
25 import org.apache.commons.lang.ObjectUtils;
26
27 import de.smartics.properties.api.config.domain.ConfigurationProperties;
28 import de.smartics.properties.api.config.domain.ConfigurationValidationException;
29 import de.smartics.properties.api.config.domain.DescribedProperty;
30 import de.smartics.properties.api.config.domain.SerializableConfigurationProperties;
31 import de.smartics.properties.api.config.domain.UnknownPropertyException;
32 import de.smartics.properties.api.config.domain.ValidatedProperty;
33 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
34 import de.smartics.properties.api.core.domain.PropertiesContext;
35 import de.smartics.properties.api.core.domain.PropertyContext;
36 import de.smartics.properties.api.core.domain.PropertyDescriptor;
37 import de.smartics.properties.api.core.domain.PropertyDescriptorRegistry;
38 import de.smartics.properties.api.core.domain.PropertyExpression;
39 import de.smartics.properties.api.core.domain.PropertyExpressionMessageBean;
40 import de.smartics.properties.api.core.domain.PropertyKey;
41 import de.smartics.properties.api.core.domain.PropertyValidationException;
42 import de.smartics.properties.api.core.domain.PropertyValueConversionException;
43 import de.smartics.properties.api.core.domain.PropertyValueResolveException;
44 import de.smartics.properties.api.core.security.PropertyValueSecurity;
45 import de.smartics.properties.api.core.security.SecurityException;
46 import de.smartics.properties.spi.config.proxy.PropertyConfigurationObjectBuilder;
47 import de.smartics.properties.spi.config.resolve.PropertyValueResolver;
48 import de.smartics.properties.spi.config.resolve.ResolveConfigurationException;
49 import de.smartics.properties.spi.config.resolve.SimplePropertyValueResolver;
50 import de.smartics.properties.spi.core.context.MandatoryPropertyContext;
51 import de.smartics.properties.spi.core.convert.BeanUtilsPropertyValueConverter;
52 import de.smartics.properties.spi.core.convert.PropertyValueConverter;
53 import de.smartics.properties.spi.core.validate.PropertyValidator;
54 import de.smartics.util.lang.Arg;
55 import de.smartics.util.lang.BlankArgumentException;
56 import de.smartics.util.lang.NullArgumentException;
57
58
59
60
61 @ThreadSafe
62 public abstract class AbstractConfigurationProperties implements
63 ConfigurationProperties, ConfigurationPropertiesSpi
64 {
65
66
67
68
69
70
71
72
73
74
75
76 private final ConfigurationKey<?> key;
77
78
79
80
81
82
83 private final PropertyDescriptorRegistry registry;
84
85
86
87
88
89
90 private final PropertyValueSecurity decrypter;
91
92
93
94
95
96
97 private final PropertyValueConverter converter =
98 new BeanUtilsPropertyValueConverter();
99
100
101
102
103 private transient PropertyValueResolver resolver;
104
105
106
107
108
109
110 private final PropertyChangeSupport support = new PropertyChangeSupport(this);
111
112
113
114
115
116
117
118
119 protected AbstractConfigurationProperties()
120 {
121 this.key = null;
122 this.registry = null;
123 this.resolver = null;
124 this.decrypter = null;
125 }
126
127
128
129
130
131
132
133
134
135
136 protected AbstractConfigurationProperties(final ConfigurationKey<?> key,
137 final PropertyDescriptorRegistry registry,
138 final PropertyValueSecurity decrypter) throws NullArgumentException
139 {
140 this.key = Arg.checkNotNull("key", key);
141 this.registry = Arg.checkNotNull("registry", registry);
142 this.decrypter = Arg.checkNotNull("decrypter", decrypter);
143 this.resolver = createResolver();
144 }
145
146
147
148
149
150
151
152 private SimplePropertyValueResolver createResolver()
153 {
154 return new SimplePropertyValueResolver(registry, this);
155 }
156
157
158
159 @Override
160 public final ConfigurationKey<?> getKey()
161 {
162 return key;
163 }
164
165 @Override
166 public final PropertyContext getContext(final PropertyDescriptor descriptor)
167 throws NullPointerException
168 {
169 Arg.checkNotNull("descriptor", descriptor);
170 return new MandatoryPropertyContext(registry.getContext(descriptor),
171 descriptor);
172 }
173
174 @Override
175 public final PropertiesContext getContext(final Class<?> declaringType)
176 throws NullPointerException
177 {
178 Arg.checkNotNull("declaringType", declaringType);
179 return registry.getContext(declaringType);
180 }
181
182
183
184
185
186
187 public final PropertyDescriptorRegistry getRegistry()
188 {
189 return registry;
190 }
191
192
193
194
195
196
197
198
199 public final PropertyValueSecurity getPropertyValueSecurity()
200 {
201 return decrypter;
202 }
203
204
205
206 @Override
207 public final DescribedProperty getProperty(final String key)
208 throws IllegalArgumentException, UnknownPropertyException
209 {
210 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
211 return getProperty(descriptor);
212 }
213
214 @Override
215 public DescribedProperty getProperty(final String key,
216 final Object defaultValue) throws IllegalArgumentException,
217 UnknownPropertyException
218 {
219 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
220 return getProperty(descriptor, defaultValue);
221 }
222
223 @Override
224 public final DescribedProperty getProperty(final PropertyKey key)
225 throws IllegalArgumentException, UnknownPropertyException
226 {
227 final PropertyDescriptor descriptor = getPropertyDescriptor(key.toString());
228 return getProperty(descriptor);
229 }
230
231 @Override
232 public final DescribedProperty getProperty(final PropertyDescriptor descriptor)
233 throws IllegalArgumentException, UnknownPropertyException
234 {
235 return getProperty(descriptor, null);
236 }
237
238 @Override
239 public final <T> T getProperties(final Class<T> propertiesInterface)
240 {
241 return getProperties(propertiesInterface, toSerializable());
242 }
243
244 @Override
245 public final <T> T getProperties(final Class<T> propertiesInterface,
246 final SerializableConfigurationProperties configuration)
247 {
248 final PropertyConfigurationObjectBuilder builder =
249 new PropertyConfigurationObjectBuilder();
250 return builder.build(propertiesInterface, configuration);
251 }
252
253 @Override
254 public final Object getPropertyValue(final String key)
255 throws IllegalArgumentException, UnknownPropertyException,
256 PropertyValidationException
257 {
258 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
259 return getPropertyValue(descriptor, null);
260 }
261
262 @Override
263 public final Object getPropertyValue(final PropertyKey key)
264 throws IllegalArgumentException, UnknownPropertyException,
265 PropertyValidationException
266 {
267 final PropertyDescriptor descriptor = getPropertyDescriptor(key.toString());
268 return getPropertyValue(descriptor, null);
269 }
270
271 @Override
272 public final Object getPropertyValue(final String key,
273 final Object defaultValue) throws NullArgumentException,
274 PropertyValidationException
275 {
276 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
277 return getPropertyValue(descriptor, defaultValue);
278 }
279
280 @Override
281 public final String getPropertyValueAsString(final String key)
282 throws NullArgumentException, PropertyValidationException
283 {
284 return getPropertyValue(key).toString();
285 }
286
287 @Override
288 public final Object getPropertyValue(final PropertyDescriptor descriptor,
289 final Object defaultValue) throws NullPointerException,
290 PropertyValueConversionException, PropertyValidationException,
291 UnknownPropertyException
292 {
293 return getValidatedProperty(descriptor, defaultValue).getValidatedValue();
294 }
295
296 @Override
297 public final String getPropertyValueAsString(final String key,
298 final Object defaultValue) throws NullArgumentException,
299 PropertyValidationException
300 {
301 return getPropertyValue(key, defaultValue).toString();
302 }
303
304 @Override
305 public final Object getPropertyValue(final PropertyDescriptor descriptor)
306 throws NullArgumentException, PropertyValidationException
307 {
308 return getPropertyValue(descriptor, null);
309 }
310
311 @Override
312 public final String getPropertyValueAsString(
313 final PropertyDescriptor descriptor) throws NullArgumentException,
314 PropertyValidationException
315 {
316 return ObjectUtils.toString(getPropertyValue(descriptor, null), null);
317 }
318
319 @Override
320 public final String getPropertyValueAsString(
321 final PropertyDescriptor descriptor, final Object defaultValue)
322 throws NullArgumentException, PropertyValidationException
323 {
324 return ObjectUtils.toString(getPropertyValue(descriptor, defaultValue),
325 null);
326 }
327
328 @Override
329 public final ValidatedProperty getValidatedProperty(final PropertyKey key,
330 final Object defaultValue) throws IllegalArgumentException,
331 UnknownPropertyException, PropertyValidationException, SecurityException
332 {
333 final PropertyDescriptor descriptor = getPropertyDescriptor(key.toString());
334 return getValidatedProperty(descriptor, defaultValue);
335 }
336
337 @Override
338 public final ValidatedProperty getValidatedProperty(final String key,
339 final Object defaultValue) throws IllegalArgumentException,
340 UnknownPropertyException, PropertyValidationException, SecurityException
341 {
342 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
343 return getValidatedProperty(descriptor, defaultValue);
344 }
345
346
347
348
349
350
351
352
353
354 protected final PropertyDescriptor getPropertyDescriptor(final String key)
355 throws BlankArgumentException, PropertyValidationException
356 {
357 Arg.checkNotBlank("key", key);
358
359 final PropertyDescriptor descriptor = registry.get(key);
360 if (descriptor == null)
361 {
362 throw new UnknownPropertyException(getKey(), key);
363 }
364 return descriptor;
365 }
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383 protected final Object resolveAndConvertAndValidate(
384 final PropertyDescriptor descriptor, final Object defaultValue,
385 final Object value) throws PropertyValueConversionException,
386 PropertyValidationException, SecurityException
387 {
388 try
389 {
390 final Object convertedValue =
391 resolveAndConvert(descriptor, value, defaultValue);
392 validate(descriptor, convertedValue);
393
394 return convertedValue;
395 }
396 catch (final PropertyValueConversionException e)
397 {
398 if (isInAdminMode())
399 {
400 return value;
401 }
402 throw e;
403 }
404 catch (final PropertyValueResolveException e)
405 {
406 if (isInAdminMode())
407 {
408 return value;
409 }
410 throw e;
411 }
412 }
413
414
415
416
417
418
419
420
421
422
423
424 public void validate(final PropertyDescriptor descriptor, final Object value,
425 final Class<?>... ifInOneOfTheseGroups)
426 {
427 final PropertyValidator validator = new PropertyValidator(isInAdminMode());
428 validator.validate(descriptor, value, ifInOneOfTheseGroups);
429 }
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 protected final Object resolveAndConvert(final PropertyDescriptor descriptor,
445 final Object value, final Object defaultValue)
446 throws PropertyValueResolveException, PropertyValueConversionException,
447 SecurityException
448 {
449 Object currentValue = value;
450 if (currentValue == null)
451 {
452 currentValue = descriptor.getDefaultExpression();
453 if (currentValue == null)
454 {
455 currentValue = defaultValue;
456 }
457 }
458
459 if (currentValue instanceof PropertyExpression)
460 {
461 final PropertyExpression expression = (PropertyExpression) currentValue;
462 currentValue = expression.getExpression();
463 }
464
465 if (currentValue instanceof String)
466 {
467 currentValue = resolveValue(descriptor, (String) currentValue);
468 }
469
470 if (descriptor.isSecured() && currentValue instanceof String)
471 {
472 currentValue = decrypter.decrypt(descriptor, (String) currentValue);
473 }
474
475 final Object convertedValue = convert(descriptor, currentValue);
476 return convertedValue;
477 }
478
479 private String resolveValue(final PropertyDescriptor descriptor,
480 final String value)
481 {
482 try
483 {
484 final String resolvedValue = resolver.resolve((String) value);
485 return resolvedValue;
486 }
487 catch (final ResolveConfigurationException e)
488 {
489 throw new PropertyValueResolveException(
490 new PropertyExpressionMessageBean(e, descriptor, e.getExpression()));
491 }
492 }
493
494 private Object convert(final PropertyDescriptor descriptor,
495 final Object currentValue)
496 {
497 if (currentValue == null)
498 {
499 return null;
500 }
501
502 return converter.convert(descriptor, currentValue);
503 }
504
505 @Override
506 public final void validate() throws ConfigurationValidationException
507 {
508 validate(false);
509 }
510
511 @Override
512 public final void validate(final Class<?>... groups)
513 throws ConfigurationValidationException
514 {
515 validate(false, groups);
516 }
517
518
519
520 @Override
521 public final void addPropertyChangeListener(final PropertyKey name,
522 final PropertyChangeListener listener) throws NullPointerException
523 {
524 support.addPropertyChangeListener(name.toString(), listener);
525 }
526
527 @Override
528 public final void removePropertyChangeListener(final PropertyKey name,
529 final PropertyChangeListener listener) throws NullPointerException
530 {
531 support.removePropertyChangeListener(name.toString(), listener);
532 }
533
534 @Override
535 public final void addPropertyChangeListener(
536 final PropertyChangeListener listener) throws NullPointerException
537 {
538 support.addPropertyChangeListener(listener);
539 }
540
541 @Override
542 public final void removePropertyChangeListener(
543 final PropertyChangeListener listener) throws NullPointerException
544 {
545 support.removePropertyChangeListener(listener);
546 }
547
548
549
550
551
552
553
554
555 protected final void firePropertyChange(final String name,
556 final String oldValue, final String newValue)
557 {
558 support.firePropertyChange(name, oldValue, newValue);
559 }
560
561
562
563 @Override
564 public ConfigurationProperties toRepresentative()
565 {
566 return this;
567 }
568
569
570
571
572
573
574
575
576 private void readObject(final ObjectInputStream in) throws IOException,
577 ClassNotFoundException
578 {
579 in.defaultReadObject();
580
581 this.resolver = createResolver();
582 }
583
584
585
586
587
588
589 @Override
590 public String toString()
591 {
592 final StringBuilder buffer = new StringBuilder();
593
594 buffer.append(key).append(":\n").append("Registry:\n").append(registry);
595
596 return buffer.toString();
597 }
598 }