1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.configuration;
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Iterator;
23 import java.util.LinkedHashSet;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.ListIterator;
27 import java.util.Set;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class CompositeConfiguration extends AbstractConfiguration
56 implements Cloneable
57 {
58
59 private List<Configuration> configList = new LinkedList<Configuration>();
60
61
62
63
64
65 private Configuration inMemoryConfiguration;
66
67
68
69
70
71 private boolean inMemoryConfigIsChild;
72
73
74
75
76
77 public CompositeConfiguration()
78 {
79 clear();
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public CompositeConfiguration(Configuration inMemoryConfiguration)
95 {
96 configList.clear();
97 this.inMemoryConfiguration = inMemoryConfiguration;
98 configList.add(inMemoryConfiguration);
99 }
100
101
102
103
104
105
106
107 public CompositeConfiguration(Collection<? extends Configuration> configurations)
108 {
109 this(new BaseConfiguration(), configurations);
110 }
111
112
113
114
115
116
117
118
119
120 public CompositeConfiguration(Configuration inMemoryConfiguration,
121 Collection<? extends Configuration> configurations)
122 {
123 this(inMemoryConfiguration);
124
125 if (configurations != null)
126 {
127 for (Configuration c : configurations)
128 {
129 addConfiguration(c);
130 }
131 }
132 }
133
134
135
136
137
138
139 public void addConfiguration(Configuration config)
140 {
141 addConfiguration(config, false);
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 public void addConfiguration(Configuration config, boolean asInMemory)
160 {
161 if (!configList.contains(config))
162 {
163 if (asInMemory)
164 {
165 replaceInMemoryConfiguration(config);
166 inMemoryConfigIsChild = true;
167 }
168
169 if (!inMemoryConfigIsChild)
170 {
171
172
173
174
175 configList.add(configList.indexOf(inMemoryConfiguration),
176 config);
177 }
178 else
179 {
180
181
182
183 configList.add(config);
184 }
185
186 if (config instanceof AbstractConfiguration)
187 {
188 ((AbstractConfiguration) config)
189 .setThrowExceptionOnMissing(isThrowExceptionOnMissing());
190 }
191 }
192 }
193
194
195
196
197
198
199 public void removeConfiguration(Configuration config)
200 {
201
202
203 if (!config.equals(inMemoryConfiguration))
204 {
205 configList.remove(config);
206 }
207 }
208
209
210
211
212
213
214 public int getNumberOfConfigurations()
215 {
216 return configList.size();
217 }
218
219
220
221
222
223
224 @Override
225 public void clear()
226 {
227 configList.clear();
228
229 inMemoryConfiguration = new BaseConfiguration();
230 ((BaseConfiguration) inMemoryConfiguration).setThrowExceptionOnMissing(isThrowExceptionOnMissing());
231 ((BaseConfiguration) inMemoryConfiguration).setListDelimiter(getListDelimiter());
232 ((BaseConfiguration) inMemoryConfiguration).setDelimiterParsingDisabled(isDelimiterParsingDisabled());
233 configList.add(inMemoryConfiguration);
234 inMemoryConfigIsChild = false;
235 }
236
237
238
239
240
241
242
243 @Override
244 protected void addPropertyDirect(String key, Object token)
245 {
246 inMemoryConfiguration.addProperty(key, token);
247 }
248
249
250
251
252
253
254
255
256 public Object getProperty(String key)
257 {
258 Configuration firstMatchingConfiguration = null;
259 for (Configuration config : configList)
260 {
261 if (config.containsKey(key))
262 {
263 firstMatchingConfiguration = config;
264 break;
265 }
266 }
267
268 if (firstMatchingConfiguration != null)
269 {
270 return firstMatchingConfiguration.getProperty(key);
271 }
272 else
273 {
274 return null;
275 }
276 }
277
278 public Iterator<String> getKeys()
279 {
280 Set<String> keys = new LinkedHashSet<String>();
281 for (Configuration config : configList)
282 {
283 for (Iterator<String> it = config.getKeys(); it.hasNext();)
284 {
285 keys.add(it.next());
286 }
287 }
288
289 return keys.iterator();
290 }
291
292 @Override
293 public Iterator<String> getKeys(String key)
294 {
295 Set<String> keys = new LinkedHashSet<String>();
296 for (Configuration config : configList)
297 {
298 for (Iterator<String> it = config.getKeys(key); it.hasNext();)
299 {
300 keys.add(it.next());
301 }
302 }
303
304 return keys.iterator();
305 }
306
307 public boolean isEmpty()
308 {
309 for (Configuration config : configList)
310 {
311 if (!config.isEmpty())
312 {
313 return false;
314 }
315 }
316
317 return true;
318 }
319
320 @Override
321 protected void clearPropertyDirect(String key)
322 {
323 for (Configuration config : configList)
324 {
325 config.clearProperty(key);
326 }
327 }
328
329 public boolean containsKey(String key)
330 {
331 for (Configuration config : configList)
332 {
333 if (config.containsKey(key))
334 {
335 return true;
336 }
337 }
338 return false;
339 }
340
341 @Override
342 public List<Object> getList(String key, List<Object> defaultValue)
343 {
344 List<Object> list = new ArrayList<Object>();
345
346
347 Iterator<Configuration> it = configList.iterator();
348 while (it.hasNext() && list.isEmpty())
349 {
350 Configuration config = it.next();
351 if (config != inMemoryConfiguration && config.containsKey(key))
352 {
353 appendListProperty(list, config, key);
354 }
355 }
356
357
358 appendListProperty(list, inMemoryConfiguration, key);
359
360 if (list.isEmpty())
361 {
362 return defaultValue;
363 }
364
365 ListIterator<Object> lit = list.listIterator();
366 while (lit.hasNext())
367 {
368 lit.set(interpolate(lit.next()));
369 }
370
371 return list;
372 }
373
374 @Override
375 public String[] getStringArray(String key)
376 {
377 List<Object> list = getList(key);
378
379
380 String[] tokens = new String[list.size()];
381
382 for (int i = 0; i < tokens.length; i++)
383 {
384 tokens[i] = String.valueOf(list.get(i));
385 }
386
387 return tokens;
388 }
389
390
391
392
393
394
395
396 public Configuration getConfiguration(int index)
397 {
398 return configList.get(index);
399 }
400
401
402
403
404
405
406
407 public Configuration getInMemoryConfiguration()
408 {
409 return inMemoryConfiguration;
410 }
411
412
413
414
415
416
417
418
419
420
421
422 @Override
423 public Object clone()
424 {
425 try
426 {
427 CompositeConfiguration copy = (CompositeConfiguration) super
428 .clone();
429 copy.clearConfigurationListeners();
430 copy.configList = new LinkedList<Configuration>();
431 copy.inMemoryConfiguration = ConfigurationUtils
432 .cloneConfiguration(getInMemoryConfiguration());
433 copy.configList.add(copy.inMemoryConfiguration);
434
435 for (Configuration config : configList)
436 {
437 if (config != getInMemoryConfiguration())
438 {
439 copy.addConfiguration(ConfigurationUtils
440 .cloneConfiguration(config));
441 }
442 }
443
444 return copy;
445 }
446 catch (CloneNotSupportedException cnex)
447 {
448
449 throw new ConfigurationRuntimeException(cnex);
450 }
451 }
452
453
454
455
456
457
458
459
460
461 @Override
462 public void setDelimiterParsingDisabled(boolean delimiterParsingDisabled)
463 {
464 if (inMemoryConfiguration instanceof AbstractConfiguration)
465 {
466 ((AbstractConfiguration) inMemoryConfiguration)
467 .setDelimiterParsingDisabled(delimiterParsingDisabled);
468 }
469 super.setDelimiterParsingDisabled(delimiterParsingDisabled);
470 }
471
472
473
474
475
476
477
478
479 @Override
480 public void setListDelimiter(char listDelimiter)
481 {
482 if (inMemoryConfiguration instanceof AbstractConfiguration)
483 {
484 ((AbstractConfiguration) inMemoryConfiguration)
485 .setListDelimiter(listDelimiter);
486 }
487 super.setListDelimiter(listDelimiter);
488 }
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513 public Configuration getSource(String key)
514 {
515 if (key == null)
516 {
517 throw new IllegalArgumentException("Key must not be null!");
518 }
519
520 Configuration source = null;
521 for (Configuration conf : configList)
522 {
523 if (conf.containsKey(key))
524 {
525 if (source != null)
526 {
527 throw new IllegalArgumentException("The key " + key
528 + " is defined by multiple sources!");
529 }
530 source = conf;
531 }
532 }
533
534 return source;
535 }
536
537
538
539
540
541
542 private void replaceInMemoryConfiguration(Configuration config)
543 {
544 if (!inMemoryConfigIsChild)
545 {
546
547 configList.remove(inMemoryConfiguration);
548 }
549 inMemoryConfiguration = config;
550 }
551
552
553
554
555
556
557
558
559
560
561 private static void appendListProperty(List<Object> dest, Configuration config,
562 String key)
563 {
564 Object value = config.getProperty(key);
565 if (value != null)
566 {
567 if (value instanceof Collection)
568 {
569 Collection<?> col = (Collection<?>) value;
570 dest.addAll(col);
571 }
572 else
573 {
574 dest.add(value);
575 }
576 }
577 }
578 }