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.List;
19
20 import javax.annotation.concurrent.ThreadSafe;
21
22 import de.smartics.properties.api.config.domain.ConfigurationPropertiesManagement;
23 import de.smartics.properties.api.config.domain.ConfigurationValidationException;
24 import de.smartics.properties.api.config.domain.DescribedProperty;
25 import de.smartics.properties.api.config.domain.Property;
26 import de.smartics.properties.api.config.domain.PropertyCollection;
27 import de.smartics.properties.api.config.domain.PropertyExpressionWithSourceMessageBean;
28 import de.smartics.properties.api.config.domain.PropertyLocation;
29 import de.smartics.properties.api.config.domain.PropertyProvider;
30 import de.smartics.properties.api.config.domain.PropertyStoreException;
31 import de.smartics.properties.api.config.domain.PropertyValidationWithSourceException;
32 import de.smartics.properties.api.config.domain.PropertyValidationWithSourceMessageBean;
33 import de.smartics.properties.api.config.domain.PropertyValueConversionWithSourceException;
34 import de.smartics.properties.api.config.domain.PropertyValueResolveWithSourceException;
35 import de.smartics.properties.api.config.domain.PropertyValueWithSourceMessageBean;
36 import de.smartics.properties.api.config.domain.UnknownPropertyException;
37 import de.smartics.properties.api.config.domain.ValidatedProperty;
38 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
39 import de.smartics.properties.api.core.app.PropertyRootException;
40 import de.smartics.properties.api.core.domain.DuplicatePropertyDeclarationsException;
41 import de.smartics.properties.api.core.domain.PropertyCode;
42 import de.smartics.properties.api.core.domain.PropertyDescriptor;
43 import de.smartics.properties.api.core.domain.PropertyDescriptorRegistry;
44 import de.smartics.properties.api.core.domain.PropertyExpression;
45 import de.smartics.properties.api.core.domain.PropertyExpressionMessageBean;
46 import de.smartics.properties.api.core.domain.PropertyKey;
47 import de.smartics.properties.api.core.domain.PropertyValidationException;
48 import de.smartics.properties.api.core.domain.PropertyValidationMessageBean;
49 import de.smartics.properties.api.core.domain.PropertyValueChangeMessageBean;
50 import de.smartics.properties.api.core.domain.PropertyValueConversionException;
51 import de.smartics.properties.api.core.domain.PropertyValueResolveException;
52 import de.smartics.properties.api.core.domain.ReadOnlyPropertyException;
53 import de.smartics.properties.api.core.security.PropertyValueSecurity;
54 import de.smartics.properties.api.core.security.SecurityException;
55 import de.smartics.properties.spi.config.validation.ConfigurationValidator;
56 import de.smartics.util.lang.Arg;
57 import de.smartics.util.lang.NullArgumentException;
58
59
60
61
62
63
64 @ThreadSafe
65 public abstract class AbstractConfigurationPropertiesManagement extends
66 AbstractAdminModeConfigurationProperties implements
67 ConfigurationPropertiesManagement, ConfigurationPropertiesManagementSpi
68 {
69
70
71
72
73
74
75
76
77
78
79
80 private final MultiSourceProperties properties;
81
82
83
84
85
86
87
88
89 protected AbstractConfigurationPropertiesManagement()
90 {
91 super();
92 this.properties = null;
93 }
94
95
96
97
98
99
100
101
102
103
104 protected AbstractConfigurationPropertiesManagement(
105 final ConfigurationKey<?> key, final PropertyDescriptorRegistry registry,
106 final PropertyValueSecurity decrypter) throws NullArgumentException
107 {
108 super(key, registry, decrypter);
109
110 this.properties = new MultiSourceProperties(key);
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125 @Override
126 public final PropertyDescriptor getDescriptor(final String key)
127 throws UnknownPropertyException
128 {
129 final PropertyDescriptor descriptor = getRegistry().get(key);
130
131 if (descriptor == null)
132 {
133 throw new UnknownPropertyException(getKey(), key);
134 }
135
136 return descriptor;
137 }
138
139 @Override
140 public final PropertyDescriptor getDescriptor(final PropertyKey key)
141 throws UnknownPropertyException
142 {
143 return getDescriptor(key.toString());
144 }
145
146 @Override
147 public final void addDescriptors(final Class<?> propertySetType)
148 throws DuplicatePropertyDeclarationsException
149 {
150 getRegistry().addDescriptors(propertySetType);
151 }
152
153 @Override
154 public final List<PropertyDescriptor> getMandatoryPropertyDescriptors()
155 {
156 return getRegistry().createMandatoryProperties();
157 }
158
159 @Override
160 public final ConfigurationPropertiesManagement addDefinitions(
161 final PropertyProvider properties) throws NullPointerException
162 {
163 this.properties.addProvider(properties);
164 addDefinitionsToStore(properties);
165 return this;
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 protected abstract void addDefinitionsToStore(
183 final PropertyProvider properties) throws PropertyStoreException;
184
185
186
187
188
189
190
191
192
193 protected abstract void setPropertiesToStore(final PropertyProvider provider)
194 throws PropertyStoreException;
195
196
197
198 @Override
199 public final DescribedProperty getProperty(final String key,
200 final Object defaultValue) throws IllegalArgumentException,
201 UnknownPropertyException
202 {
203 final PropertyDescriptor descriptor = getDescriptor(key);
204 return getProperty(descriptor, defaultValue);
205 }
206
207 @Override
208 public final DescribedProperty getProperty(
209 final PropertyDescriptor descriptor, final Object defaultValue)
210 throws IllegalArgumentException, UnknownPropertyException
211 {
212 final DescribedProperty property = getPropertyInternal(descriptor);
213
214 return property;
215 }
216
217 private DescribedProperty getPropertyInternal(
218 final PropertyDescriptor descriptor)
219 {
220 final String name = descriptor.getKey().toString();
221 final Property property = getPropertyFromStore(name);
222
223
224
225
226
227
228
229 final DescribedProperty describedProperty =
230 new DescribedProperty(this.getKey(), descriptor, property);
231
232 return describedProperty;
233 }
234
235 @Override
236 public Object getPropertyAsType(final PropertyDescriptor descriptor)
237 throws IllegalArgumentException, PropertyValueConversionException,
238 SecurityException, PropertyRootException
239 {
240 final Property property = getProperty(descriptor);
241 final String plainValue = property.getValue();
242 final Object resolvedValue =
243 resolveAndConvert(descriptor, plainValue, null);
244 return resolvedValue;
245 }
246
247 @Override
248 public final ValidatedProperty getValidatedProperty(
249 final PropertyDescriptor descriptor, final Object defaultValue)
250 throws IllegalArgumentException, UnknownPropertyException,
251 PropertyValidationException, SecurityException
252 {
253 final Property property = getProperty(descriptor, defaultValue);
254
255 final Object plainValue = property.getValue();
256 if (plainValue == null && defaultValue == null && descriptor.isMandatory())
257 {
258
259
260
261
262 final PropertyValidationMessageBean message =
263 new PropertyValidationMessageBean(descriptor,
264 descriptor.getConstraints(), plainValue);
265 throw new PropertyValidationException(message);
266 }
267
268 try
269 {
270 final Object resolvedValue =
271 resolveAndConvertAndValidate(descriptor, defaultValue, plainValue);
272 final DescribedProperty describedProperty =
273 new DescribedProperty(getKey(), descriptor, property);
274 return new ValidatedProperty(describedProperty,
275 getExpression(descriptor), resolvedValue);
276 }
277 catch (final PropertyValueResolveException e)
278 {
279 throw wrapWithPropertyValueSourceInformation(e, descriptor, property);
280 }
281 catch (final PropertyValueConversionException e)
282 {
283 throw wrapWithPropertyValueSourceInformation(e, property);
284 }
285 catch (final PropertyValidationException e)
286 {
287 throw wrapWithPropertyValueSourceInformation(e, property);
288 }
289 }
290
291 private static String getExpression(final PropertyDescriptor descriptor)
292 {
293 final PropertyExpression expression = descriptor.getDefaultExpression();
294 return expression != null ? expression.getExpression() : null;
295 }
296
297 @Override
298 public final Property setProperty(final PropertyKey key, final String value)
299 throws NullPointerException, PropertyValidationException,
300 ReadOnlyPropertyException
301 {
302 Arg.checkNotNull("key", key);
303 checkWritable(key, value);
304
305 final String name = key.toString();
306 return setPropertyAndFireEvent(name, value);
307 }
308
309 private Property setPropertyAndFireEvent(final String name, final String value)
310 throws NullPointerException, PropertyValidationException,
311 ReadOnlyPropertyException
312 {
313 final String normalized = provideSecurity(name, value);
314 final Property oldProperty = setPropertyToStore(name, normalized);
315 firePropertyChange(name, oldProperty != null ? oldProperty.getValue()
316 : null, normalized);
317 return oldProperty;
318 }
319
320 private String provideSecurity(final String name, final String value)
321 {
322 if (value != null)
323 {
324 final PropertyDescriptor descriptor = getRegistry().get(name);
325 if (descriptor.isSecured())
326 {
327 final String encryptedValue =
328 getPropertyValueSecurity().encrypt(descriptor, value);
329 return encryptedValue;
330 }
331 }
332
333 return value;
334 }
335
336 @Override
337 public final Property unsetProperty(final PropertyKey key)
338 throws NullPointerException, ReadOnlyPropertyException
339 {
340 Arg.checkNotNull("key", key);
341 checkWritable(key, null);
342
343 final String name = key.toString();
344 final Property oldProperty = deletePropertyInStore(name);
345 firePropertyChange(name, oldProperty.getValue(), null);
346 return oldProperty;
347 }
348
349 @Override
350 public final void validate(final boolean lenient, final Class<?>... groups)
351 throws ConfigurationValidationException
352 {
353 final ConfigurationValidator validator =
354 new ConfigurationValidator(this, lenient);
355 final PropertyCollection propertyCollection =
356 getPropertyCollectionFromStore();
357 validator.validate(propertyCollection, groups);
358 }
359
360 @Override
361 public final void validate(final PropertyDescriptor descriptor,
362 final Class<?>... ifInOneOfTheseGroups)
363 throws ConfigurationValidationException
364 {
365 final Object value = getPropertyValue(descriptor);
366 validate(descriptor, value, ifInOneOfTheseGroups);
367 }
368
369 @Override
370 public final void validate(final PropertyDescriptor descriptor,
371 final String value, final Class<?>... ifInOneOfTheseGroups)
372 throws ConfigurationValidationException
373 {
374 final ConfigurationValidator validator =
375 new ConfigurationValidator(this, false);
376 final Object valueAsType = resolveAndConvert(descriptor, value, null);
377
378 validator.validate(descriptor, valueAsType, ifInOneOfTheseGroups);
379 }
380
381
382
383
384
385
386
387
388
389
390 @Override
391 public void flush()
392 {
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408 protected final Property setPropertyToStore(final String name,
409 final String value) throws NullPointerException
410 {
411 return getPropertyStoreAccessor().setPropertyToStore(name, value);
412 }
413
414
415
416
417
418
419
420
421 protected final PropertyCollection getPropertyCollectionFromStore()
422 {
423 return getPropertyStoreAccessor().getPropertyCollectionFromStore();
424 }
425
426
427
428
429
430
431
432
433
434 protected final Property deletePropertyInStore(final String name)
435 {
436 return getPropertyStoreAccessor().deletePropertyInStore(name);
437 }
438
439
440
441
442
443
444
445
446
447
448 protected final Property getPropertyFromStore(final String name)
449 {
450 return getPropertyStoreAccessor().getPropertyFromStore(name);
451 }
452
453
454
455
456
457
458
459
460
461
462
463
464 private void checkWritable(final PropertyKey key, final Object value)
465 throws ReadOnlyPropertyException, UnknownPropertyException
466 {
467 if (isInAdminMode())
468 {
469 return;
470 }
471
472 final PropertyDescriptor descriptor = getDescriptor(key);
473
474 if (!descriptor.isRuntimeMutable())
475 {
476 final Object currentValue = getPropertyAsType(descriptor);
477 throw new ReadOnlyPropertyException(new PropertyValueChangeMessageBean(
478 PropertyCode.READ_ONLY, descriptor, currentValue, value));
479 }
480 }
481
482 private static PropertyValueResolveException wrapWithPropertyValueSourceInformation(
483 final PropertyValueResolveException e,
484 final PropertyDescriptor descriptor, final Property property)
485 {
486 final PropertyValueResolveException cause =
487 isResolvementFailureOfPlaceholder(e, property)
488 ? new PropertyValueResolveException(
489 new PropertyExpressionMessageBean(e, descriptor,
490 property.getValue())) : e;
491
492 if (!(cause instanceof PropertyValueResolveWithSourceException))
493 {
494 final PropertyLocation source = property.getSource();
495 return new PropertyValueResolveWithSourceException(
496 new PropertyExpressionWithSourceMessageBean(cause, source));
497 }
498
499 return e;
500 }
501
502 private static boolean isResolvementFailureOfPlaceholder(
503 final PropertyValueResolveException e, final Property property)
504 {
505 return !property.getName().equals(e.getPropertyKey().getName());
506 }
507
508 private static PropertyValueConversionException wrapWithPropertyValueSourceInformation(
509 final PropertyValueConversionException e, final Property property)
510 {
511 final PropertyLocation source = property.getSource();
512 return new PropertyValueConversionWithSourceException(
513 new PropertyValueWithSourceMessageBean(e, source));
514 }
515
516 private static PropertyValidationException wrapWithPropertyValueSourceInformation(
517 final PropertyValidationException e, final Property property)
518 {
519 final PropertyLocation source = property.getSource();
520 return new PropertyValidationWithSourceException(
521 new PropertyValidationWithSourceMessageBean(e, source));
522 }
523
524
525
526 }