1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration2.builder;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertFalse;
21 import static org.junit.jupiter.api.Assertions.assertNotSame;
22 import static org.junit.jupiter.api.Assertions.assertSame;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.verifyNoMoreInteractions;
28 import static org.mockito.Mockito.when;
29
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.concurrent.CountDownLatch;
36 import java.util.concurrent.TimeUnit;
37
38 import org.apache.commons.configuration2.BaseConfiguration;
39 import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
40 import org.apache.commons.configuration2.Configuration;
41 import org.apache.commons.configuration2.Initializable;
42 import org.apache.commons.configuration2.PropertiesConfiguration;
43 import org.apache.commons.configuration2.XMLConfiguration;
44 import org.apache.commons.configuration2.beanutils.BeanCreationContext;
45 import org.apache.commons.configuration2.beanutils.BeanDeclaration;
46 import org.apache.commons.configuration2.beanutils.BeanFactory;
47 import org.apache.commons.configuration2.beanutils.BeanHelper;
48 import org.apache.commons.configuration2.beanutils.DefaultBeanFactory;
49 import org.apache.commons.configuration2.beanutils.XMLBeanDeclaration;
50 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
51 import org.apache.commons.configuration2.convert.ListDelimiterHandler;
52 import org.apache.commons.configuration2.event.ConfigurationErrorEvent;
53 import org.apache.commons.configuration2.event.ConfigurationEvent;
54 import org.apache.commons.configuration2.event.ErrorListenerTestImpl;
55 import org.apache.commons.configuration2.event.EventListener;
56 import org.apache.commons.configuration2.event.EventListenerRegistrationData;
57 import org.apache.commons.configuration2.event.EventListenerTestImpl;
58 import org.apache.commons.configuration2.ex.ConfigurationException;
59 import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
60 import org.apache.commons.configuration2.reloading.ReloadingController;
61 import org.apache.commons.configuration2.reloading.ReloadingDetector;
62 import org.junit.jupiter.api.BeforeAll;
63 import org.junit.jupiter.api.Test;
64
65
66
67
68 public class TestBasicConfigurationBuilder {
69
70
71
72 private static final class AccessBuilderThread extends Thread {
73
74 private final CountDownLatch startLatch;
75
76
77 private final CountDownLatch endLatch;
78
79
80 private final ConfigurationBuilder<?> builder;
81
82
83 private volatile Object result;
84
85
86
87
88
89
90
91
92 public AccessBuilderThread(final CountDownLatch lstart, final CountDownLatch lend, final ConfigurationBuilder<?> bldr) {
93 startLatch = lstart;
94 endLatch = lend;
95 builder = bldr;
96 }
97
98 @Override
99 public void run() {
100 try {
101 startLatch.await();
102 result = builder.getConfiguration();
103 } catch (final Exception ex) {
104 result = ex;
105 } finally {
106 endLatch.countDown();
107 }
108 }
109 }
110
111
112
113
114 private static final class BasicConfigurationBuilderInitFailImpl extends BasicConfigurationBuilder<PropertiesConfiguration> {
115 public BasicConfigurationBuilderInitFailImpl(final boolean allowFailOnInit) {
116 super(PropertiesConfiguration.class, null, allowFailOnInit);
117 }
118
119
120
121
122 @Override
123 protected void initResultInstance(final PropertiesConfiguration obj) throws ConfigurationException {
124 throw new ConfigurationException("Initialization test exception!");
125 }
126 }
127
128
129
130
131 public static class InitializableConfiguration extends BaseConfiguration implements Initializable {
132
133 private String initProperty;
134
135 public String getInitProperty() {
136 return initProperty;
137 }
138
139
140
141
142
143 @Override
144 public void initialize() {
145 initProperty = "Initialized with flag " + isThrowExceptionOnMissing();
146 }
147 }
148
149
150 private static ListDelimiterHandler listHandler;
151
152
153
154
155
156
157 @SuppressWarnings("unchecked")
158 private static EventListener<ConfigurationEvent> createEventListener() {
159 return mock(EventListener.class);
160 }
161
162
163
164
165
166
167 private static Map<String, Object> createTestParameters() {
168 final Map<String, Object> params = new HashMap<>();
169 params.put("throwExceptionOnMissing", Boolean.TRUE);
170 params.put("listDelimiterHandler", listHandler);
171 return params;
172 }
173
174 @BeforeAll
175 public static void setUpBeforeClass() throws Exception {
176 listHandler = new DefaultListDelimiterHandler(';');
177 }
178
179
180
181
182 @Test
183 public void testAddConfigurationListener() throws ConfigurationException {
184 final EventListener<ConfigurationEvent> l1 = createEventListener();
185 final EventListener<ConfigurationEvent> l2 = createEventListener();
186 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
187 builder.addEventListener(ConfigurationEvent.ANY, l1);
188 final PropertiesConfiguration config = builder.getConfiguration();
189 builder.addEventListener(ConfigurationEvent.ANY, l2);
190 final Collection<EventListener<? super ConfigurationEvent>> listeners = config.getEventListeners(ConfigurationEvent.ANY);
191 assertTrue(listeners.contains(l1));
192 assertTrue(listeners.contains(l2));
193 }
194
195
196
197
198 @Test
199 public void testAddParameters() {
200 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class,
201 createTestParameters());
202 final Map<String, Object> params = createTestParameters();
203 params.put("anotherParameter", "value");
204 assertSame(builder, builder.addParameters(params));
205 final Map<String, Object> params2 = builder.getParameters();
206 assertTrue(params2.keySet().containsAll(createTestParameters().keySet()));
207 assertEquals("value", params2.get("anotherParameter"));
208 }
209
210
211
212
213 @Test
214 public void testAddParametersNull() {
215 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class,
216 createTestParameters());
217 final Map<String, Object> params = builder.getParameters();
218 builder.addParameters(null);
219 assertEquals(params, builder.getParameters());
220 }
221
222
223
224
225 @Test
226 public void testBeanHelperInConfiguration() throws ConfigurationException {
227 final Set<Class<?>> classesPassedToFactory = new HashSet<>();
228 final BeanFactory factory = new DefaultBeanFactory() {
229 @Override
230 public Object createBean(final BeanCreationContext bcc) throws Exception {
231 classesPassedToFactory.add(bcc.getBeanClass());
232 return super.createBean(bcc);
233 }
234 };
235 final BeanHelper helper = new BeanHelper(factory);
236 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
237 builder.configure(new BasicBuilderParameters().setBeanHelper(helper));
238 final PropertiesConfiguration config = builder.getConfiguration();
239 assertTrue(classesPassedToFactory.contains(config.getClass()));
240 }
241
242
243
244
245 @Test
246 public void testConfigure() {
247 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class)
248 .configure(new BasicBuilderParameters().setListDelimiterHandler(listHandler).setThrowExceptionOnMissing(true));
249 final Map<String, Object> params2 = new HashMap<>(builder.getParameters());
250 assertEquals(createTestParameters(), params2);
251 }
252
253
254
255
256 @Test
257 public void testConnectToReloadingController() throws ConfigurationException {
258 final ReloadingDetector detector = mock(ReloadingDetector.class);
259 final ReloadingController controller = new ReloadingController(detector);
260 final BasicConfigurationBuilder<Configuration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
261 final Configuration configuration = builder.getConfiguration();
262
263 when(detector.isReloadingRequired()).thenReturn(Boolean.TRUE);
264
265 builder.connectToReloadingController(controller);
266 controller.checkForReloading(null);
267 assertTrue(controller.isInReloadingState());
268 assertNotSame(configuration, builder.getConfiguration());
269 assertFalse(controller.isInReloadingState());
270
271 verify(detector).isReloadingRequired();
272 verify(detector).reloadingPerformed();
273 verifyNoMoreInteractions(detector);
274 }
275
276
277
278
279 @Test
280 public void testConnectToReloadingControllerNull() {
281 final BasicConfigurationBuilder<Configuration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
282 assertThrows(IllegalArgumentException.class, () -> builder.connectToReloadingController(null));
283 }
284
285
286
287
288 @Test
289 public void testCopyEventListeners() throws ConfigurationException {
290 final EventListener<ConfigurationEvent> l1 = createEventListener();
291 final EventListener<ConfigurationEvent> l2 = createEventListener();
292 final EventListener<ConfigurationErrorEvent> l3 = new ErrorListenerTestImpl(null);
293 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
294 builder.addEventListener(ConfigurationEvent.ANY, l1);
295 builder.addEventListener(ConfigurationEvent.ANY_HIERARCHICAL, l2);
296 builder.addEventListener(ConfigurationErrorEvent.ANY, l3);
297 final BasicConfigurationBuilder<XMLConfiguration> builder2 = new BasicConfigurationBuilder<>(XMLConfiguration.class);
298 builder.copyEventListeners(builder2);
299 final XMLConfiguration config = builder2.getConfiguration();
300 Collection<EventListener<? super ConfigurationEvent>> listeners = config.getEventListeners(ConfigurationEvent.ANY);
301 assertEquals(1, listeners.size());
302 assertTrue(listeners.contains(l1));
303 listeners = config.getEventListeners(ConfigurationEvent.ANY_HIERARCHICAL);
304 assertEquals(2, listeners.size());
305 assertTrue(listeners.contains(l1));
306 assertTrue(listeners.contains(l2));
307 final Collection<EventListener<? super ConfigurationErrorEvent>> errListeners = config.getEventListeners(ConfigurationErrorEvent.ANY);
308 assertEquals(1, errListeners.size());
309 assertTrue(errListeners.contains(l3));
310 }
311
312
313
314
315 @Test
316 public void testEventListenerConfiguration() throws ConfigurationException {
317 final EventListenerTestImpl listener1 = new EventListenerTestImpl(null);
318 final EventListenerRegistrationData<ConfigurationErrorEvent> regData = new EventListenerRegistrationData<>(ConfigurationErrorEvent.WRITE,
319 new ErrorListenerTestImpl(null));
320 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class)
321 .configure(new EventListenerParameters().addEventListener(ConfigurationEvent.ANY, listener1).addEventListener(regData));
322 final PropertiesConfiguration config = builder.getConfiguration();
323 assertTrue(config.getEventListeners(ConfigurationEvent.ANY).contains(listener1));
324 assertTrue(config.getEventListeners(regData.getEventType()).contains(regData.getListener()));
325 }
326
327
328
329
330 @Test
331 public void testGetConfiguration() throws ConfigurationException {
332 final PropertiesConfiguration config = new BasicConfigurationBuilder<>(PropertiesConfiguration.class)
333 .configure(new BasicBuilderParameters().setListDelimiterHandler(listHandler).setThrowExceptionOnMissing(true)).getConfiguration();
334 assertTrue(config.isThrowExceptionOnMissing());
335 assertEquals(listHandler, config.getListDelimiterHandler());
336 }
337
338
339
340
341 @Test
342 public void testGetConfigurationConcurrently() throws Exception {
343 final int threadCount = 32;
344 final CountDownLatch startLatch = new CountDownLatch(1);
345 final CountDownLatch endLatch = new CountDownLatch(threadCount);
346 final ConfigurationBuilder<?> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
347 final AccessBuilderThread[] threads = new AccessBuilderThread[threadCount];
348 for (int i = 0; i < threadCount; i++) {
349 threads[i] = new AccessBuilderThread(startLatch, endLatch, builder);
350 threads[i].start();
351 }
352 startLatch.countDown();
353 assertTrue(endLatch.await(5, TimeUnit.SECONDS));
354 final Set<Object> results = new HashSet<>();
355 for (final AccessBuilderThread t : threads) {
356 results.add(t.result);
357 }
358 assertEquals(1, results.size());
359 }
360
361
362
363
364 @Test
365 public void testGetParametersModify() {
366 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class,
367 createTestParameters());
368 final Map<String, Object> parameters = builder.getParameters();
369 assertThrows(UnsupportedOperationException.class, parameters::clear);
370 }
371
372
373
374
375 @Test
376 public void testGetResultDeclarationInvalidBeanClass() {
377 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<PropertiesConfiguration>(PropertiesConfiguration.class,
378 createTestParameters()) {
379 @Override
380 protected BeanDeclaration createResultDeclaration(final Map<String, Object> params) {
381 return new XMLBeanDeclaration(new BaseHierarchicalConfiguration(), "bean", true, Object.class.getName());
382 }
383 };
384 assertThrows(ConfigurationRuntimeException.class, builder::getConfiguration);
385 }
386
387
388
389
390 @Test
391 public void testInitializableCalled() throws ConfigurationException {
392 final BasicConfigurationBuilder<InitializableConfiguration> builder = new BasicConfigurationBuilder<>(InitializableConfiguration.class);
393 builder.configure(new BasicBuilderParameters().setThrowExceptionOnMissing(true));
394 final InitializableConfiguration config = builder.getConfiguration();
395 assertEquals("Initialized with flag true", config.getInitProperty());
396 }
397
398
399
400
401 @Test
402 public void testInitializationErrorAllowed() throws ConfigurationException {
403 final BasicConfigurationBuilderInitFailImpl builder = new BasicConfigurationBuilderInitFailImpl(true);
404 final PropertiesConfiguration config = builder.getConfiguration();
405 assertTrue(config.isEmpty());
406 }
407
408
409
410
411 @Test
412 public void testInitializationErrorNotAllowed() {
413 final BasicConfigurationBuilderInitFailImpl builder = new BasicConfigurationBuilderInitFailImpl(false);
414 assertThrows(ConfigurationException.class, builder::getConfiguration);
415 }
416
417
418
419
420 @Test
421 public void testInitNoClass() {
422 assertThrows(IllegalArgumentException.class, () -> new BasicConfigurationBuilder<Configuration>(null));
423 }
424
425
426
427
428 @Test
429 public void testInitWithParameters() {
430 final Map<String, Object> params = createTestParameters();
431 final BasicConfigurationBuilder<Configuration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class, params);
432 final Map<String, Object> params2 = new HashMap<>(builder.getParameters());
433 assertEquals(createTestParameters(), params2);
434 }
435
436
437
438
439 @Test
440 public void testInitWithParametersDefensiveCopy() {
441 final Map<String, Object> params = createTestParameters();
442 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class, params);
443 params.put("anotherParameter", "value");
444 final Map<String, Object> params2 = new HashMap<>(builder.getParameters());
445 assertEquals(createTestParameters(), params2);
446 }
447
448
449
450
451 @Test
452 public void testInitWithParametersNull() {
453 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class, null);
454 assertTrue(builder.getParameters().isEmpty());
455 }
456
457
458
459
460 @Test
461 public void testRemoveConfigurationListener() throws ConfigurationException {
462 final EventListener<ConfigurationEvent> l1 = createEventListener();
463 final EventListener<ConfigurationEvent> l2 = createEventListener();
464 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class);
465 builder.addEventListener(ConfigurationEvent.ANY_HIERARCHICAL, l1);
466 builder.addEventListener(ConfigurationEvent.ANY, l2);
467 assertTrue(builder.removeEventListener(ConfigurationEvent.ANY, l2));
468 final PropertiesConfiguration config = builder.getConfiguration();
469 assertFalse(config.getEventListeners(ConfigurationEvent.ANY).contains(l2));
470 assertTrue(config.getEventListeners(ConfigurationEvent.ANY_HIERARCHICAL).contains(l1));
471 builder.removeEventListener(ConfigurationEvent.ANY_HIERARCHICAL, l1);
472 assertFalse(config.getEventListeners(ConfigurationEvent.ANY_HIERARCHICAL).contains(l1));
473 }
474
475
476
477
478
479 @Test
480 public void testRemoveConfigurationListenersOnReset() throws ConfigurationException {
481 final EventListenerTestImpl listener = new EventListenerTestImpl(null);
482 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class)
483 .configure(new EventListenerParameters().addEventListener(ConfigurationEvent.ANY, listener));
484 final PropertiesConfiguration config = builder.getConfiguration();
485 builder.resetResult();
486 config.addProperty("foo", "bar");
487 listener.done();
488 }
489
490
491
492
493 @Test
494 public void testReservedParameter() throws ConfigurationException {
495 final Map<String, Object> params = new HashMap<>();
496 params.put("throwExceptionOnMissing", Boolean.TRUE);
497 params.put("config-test", "a test");
498 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class, params);
499 final PropertiesConfiguration config = builder.getConfiguration();
500 assertTrue(config.isThrowExceptionOnMissing());
501 }
502
503
504
505
506 @Test
507 public void testReset() throws ConfigurationException {
508 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class,
509 createTestParameters());
510 final PropertiesConfiguration config = builder.getConfiguration();
511 builder.reset();
512 final PropertiesConfiguration config2 = builder.getConfiguration();
513 assertNotSame(config, config2);
514 assertFalse(config2.isThrowExceptionOnMissing());
515 }
516
517
518
519
520 @Test
521 public void testResetParameters() {
522 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class,
523 createTestParameters());
524 builder.resetParameters();
525 assertTrue(builder.getParameters().isEmpty());
526 }
527
528
529
530
531 @Test
532 public void testResetResult() throws ConfigurationException {
533 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class,
534 createTestParameters());
535 final PropertiesConfiguration config = builder.getConfiguration();
536 builder.resetResult();
537 final PropertiesConfiguration config2 = builder.getConfiguration();
538 assertNotSame(config, config2);
539 assertTrue(config2.isThrowExceptionOnMissing());
540 }
541
542
543
544
545 @Test
546 public void testSetParameters() {
547 final Map<String, Object> params1 = new HashMap<>();
548 params1.put("someParameter", "value");
549 final BasicConfigurationBuilder<PropertiesConfiguration> builder = new BasicConfigurationBuilder<>(PropertiesConfiguration.class, params1);
550 assertSame(builder, builder.setParameters(createTestParameters()));
551 final Map<String, Object> params2 = new HashMap<>(builder.getParameters());
552 assertEquals(createTestParameters(), params2);
553 }
554 }