1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration;
18
19 import java.math.BigDecimal;
20 import java.math.BigInteger;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.Set;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.ConcurrentMap;
31
32 import org.apache.commons.configuration.event.ConfigurationErrorListener;
33 import org.apache.commons.configuration.event.ConfigurationListener;
34 import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
35 import org.apache.commons.configuration.tree.ConfigurationNode;
36 import org.apache.commons.configuration.tree.ExpressionEngine;
37 import org.apache.commons.configuration.tree.NodeCombiner;
38 import org.apache.commons.lang.text.StrSubstitutor;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42
43
44
45
46
47
48
49
50
51
52 public class DynamicCombinedConfiguration extends CombinedConfiguration
53 {
54
55
56
57 private static ThreadLocal<Boolean> recursive = new ThreadLocal<Boolean>()
58 {
59 @Override
60 protected synchronized Boolean initialValue()
61 {
62 return Boolean.FALSE;
63 }
64 };
65
66
67 private final ConcurrentMap<String, CombinedConfiguration> configs =
68 new ConcurrentHashMap<String, CombinedConfiguration>();
69
70
71 private List<ConfigData> configurations = new ArrayList<ConfigData>();
72
73
74 private Map<String, AbstractConfiguration> namedConfigurations =
75 new HashMap<String, AbstractConfiguration>();
76
77
78 private String keyPattern;
79
80
81 private NodeCombiner nodeCombiner;
82
83
84 private String loggerName = DynamicCombinedConfiguration.class.getName();
85
86
87 private StrSubstitutor localSubst = new StrSubstitutor(new ConfigurationInterpolator());
88
89
90
91
92
93
94
95
96 public DynamicCombinedConfiguration(NodeCombiner comb)
97 {
98 super();
99 setNodeCombiner(comb);
100 setIgnoreReloadExceptions(false);
101 setLogger(LogFactory.getLog(DynamicCombinedConfiguration.class));
102 }
103
104
105
106
107
108
109
110 public DynamicCombinedConfiguration()
111 {
112 super();
113 setIgnoreReloadExceptions(false);
114 setLogger(LogFactory.getLog(DynamicCombinedConfiguration.class));
115 }
116
117 public void setKeyPattern(String pattern)
118 {
119 this.keyPattern = pattern;
120 }
121
122 public String getKeyPattern()
123 {
124 return this.keyPattern;
125 }
126
127
128
129
130
131 public void setLoggerName(String name)
132 {
133 this.loggerName = name;
134 }
135
136
137
138
139
140
141
142 @Override
143 public NodeCombiner getNodeCombiner()
144 {
145 return nodeCombiner;
146 }
147
148
149
150
151
152
153
154
155
156
157 @Override
158 public void setNodeCombiner(NodeCombiner nodeCombiner)
159 {
160 if (nodeCombiner == null)
161 {
162 throw new IllegalArgumentException(
163 "Node combiner must not be null!");
164 }
165 this.nodeCombiner = nodeCombiner;
166 invalidateAll();
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 @Override
185 public void addConfiguration(AbstractConfiguration config, String name,
186 String at)
187 {
188 ConfigData cd = new ConfigData(config, name, at);
189 configurations.add(cd);
190 if (name != null)
191 {
192 namedConfigurations.put(name, config);
193 }
194 }
195
196
197
198
199
200
201 @Override
202 public int getNumberOfConfigurations()
203 {
204 return configurations.size();
205 }
206
207
208
209
210
211
212
213
214
215 @Override
216 public Configuration getConfiguration(int index)
217 {
218 ConfigData cd = configurations.get(index);
219 return cd.getConfiguration();
220 }
221
222
223
224
225
226
227
228
229 @Override
230 public Configuration getConfiguration(String name)
231 {
232 return namedConfigurations.get(name);
233 }
234
235
236
237
238
239
240
241
242
243 @Override
244 public Set<String> getConfigurationNames()
245 {
246 return namedConfigurations.keySet();
247 }
248
249
250
251
252
253
254
255
256 @Override
257 public Configuration removeConfiguration(String name)
258 {
259 Configuration conf = getConfiguration(name);
260 if (conf != null)
261 {
262 removeConfiguration(conf);
263 }
264 return conf;
265 }
266
267
268
269
270
271
272
273 @Override
274 public boolean removeConfiguration(Configuration config)
275 {
276 for (int index = 0; index < getNumberOfConfigurations(); index++)
277 {
278 if (configurations.get(index).getConfiguration() == config)
279 {
280 removeConfigurationAt(index);
281
282 }
283 }
284
285 return super.removeConfiguration(config);
286 }
287
288
289
290
291
292
293
294 @Override
295 public Configuration removeConfigurationAt(int index)
296 {
297 ConfigData cd = configurations.remove(index);
298 if (cd.getName() != null)
299 {
300 namedConfigurations.remove(cd.getName());
301 }
302 return super.removeConfigurationAt(index);
303 }
304
305
306
307
308
309
310
311 @Override
312 public ConfigurationNode getRootNode()
313 {
314 return getCurrentConfig().getRootNode();
315 }
316
317 @Override
318 public void setRootNode(ConfigurationNode rootNode)
319 {
320 if (configs != null)
321 {
322 this.getCurrentConfig().setRootNode(rootNode);
323 }
324 else
325 {
326 super.setRootNode(rootNode);
327 }
328 }
329
330 @Override
331 public void addProperty(String key, Object value)
332 {
333 this.getCurrentConfig().addProperty(key, value);
334 }
335
336 @Override
337 public void clear()
338 {
339 if (configs != null)
340 {
341 this.getCurrentConfig().clear();
342 }
343 }
344
345 @Override
346 public void clearProperty(String key)
347 {
348 this.getCurrentConfig().clearProperty(key);
349 }
350
351 @Override
352 public boolean containsKey(String key)
353 {
354 return this.getCurrentConfig().containsKey(key);
355 }
356
357 @Override
358 public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)
359 {
360 return this.getCurrentConfig().getBigDecimal(key, defaultValue);
361 }
362
363 @Override
364 public BigDecimal getBigDecimal(String key)
365 {
366 return this.getCurrentConfig().getBigDecimal(key);
367 }
368
369 @Override
370 public BigInteger getBigInteger(String key, BigInteger defaultValue)
371 {
372 return this.getCurrentConfig().getBigInteger(key, defaultValue);
373 }
374
375 @Override
376 public BigInteger getBigInteger(String key)
377 {
378 return this.getCurrentConfig().getBigInteger(key);
379 }
380
381 @Override
382 public boolean getBoolean(String key, boolean defaultValue)
383 {
384 return this.getCurrentConfig().getBoolean(key, defaultValue);
385 }
386
387 @Override
388 public Boolean getBoolean(String key, Boolean defaultValue)
389 {
390 return this.getCurrentConfig().getBoolean(key, defaultValue);
391 }
392
393 @Override
394 public boolean getBoolean(String key)
395 {
396 return this.getCurrentConfig().getBoolean(key);
397 }
398
399 @Override
400 public byte getByte(String key, byte defaultValue)
401 {
402 return this.getCurrentConfig().getByte(key, defaultValue);
403 }
404
405 @Override
406 public Byte getByte(String key, Byte defaultValue)
407 {
408 return this.getCurrentConfig().getByte(key, defaultValue);
409 }
410
411 @Override
412 public byte getByte(String key)
413 {
414 return this.getCurrentConfig().getByte(key);
415 }
416
417 @Override
418 public double getDouble(String key, double defaultValue)
419 {
420 return this.getCurrentConfig().getDouble(key, defaultValue);
421 }
422
423 @Override
424 public Double getDouble(String key, Double defaultValue)
425 {
426 return this.getCurrentConfig().getDouble(key, defaultValue);
427 }
428
429 @Override
430 public double getDouble(String key)
431 {
432 return this.getCurrentConfig().getDouble(key);
433 }
434
435 @Override
436 public float getFloat(String key, float defaultValue)
437 {
438 return this.getCurrentConfig().getFloat(key, defaultValue);
439 }
440
441 @Override
442 public Float getFloat(String key, Float defaultValue)
443 {
444 return this.getCurrentConfig().getFloat(key, defaultValue);
445 }
446
447 @Override
448 public float getFloat(String key)
449 {
450 return this.getCurrentConfig().getFloat(key);
451 }
452
453 @Override
454 public int getInt(String key, int defaultValue)
455 {
456 return this.getCurrentConfig().getInt(key, defaultValue);
457 }
458
459 @Override
460 public int getInt(String key)
461 {
462 return this.getCurrentConfig().getInt(key);
463 }
464
465 @Override
466 public Integer getInteger(String key, Integer defaultValue)
467 {
468 return this.getCurrentConfig().getInteger(key, defaultValue);
469 }
470
471 @Override
472 public Iterator<String> getKeys()
473 {
474 return this.getCurrentConfig().getKeys();
475 }
476
477 @Override
478 public Iterator<String> getKeys(String prefix)
479 {
480 return this.getCurrentConfig().getKeys(prefix);
481 }
482
483 @Override
484 public List<Object> getList(String key, List<Object> defaultValue)
485 {
486 return this.getCurrentConfig().getList(key, defaultValue);
487 }
488
489 @Override
490 public List<Object> getList(String key)
491 {
492 return this.getCurrentConfig().getList(key);
493 }
494
495 @Override
496 public long getLong(String key, long defaultValue)
497 {
498 return this.getCurrentConfig().getLong(key, defaultValue);
499 }
500
501 @Override
502 public Long getLong(String key, Long defaultValue)
503 {
504 return this.getCurrentConfig().getLong(key, defaultValue);
505 }
506
507 @Override
508 public long getLong(String key)
509 {
510 return this.getCurrentConfig().getLong(key);
511 }
512
513 @Override
514 public Properties getProperties(String key)
515 {
516 return this.getCurrentConfig().getProperties(key);
517 }
518
519 @Override
520 public Object getProperty(String key)
521 {
522 return this.getCurrentConfig().getProperty(key);
523 }
524
525 @Override
526 public short getShort(String key, short defaultValue)
527 {
528 return this.getCurrentConfig().getShort(key, defaultValue);
529 }
530
531 @Override
532 public Short getShort(String key, Short defaultValue)
533 {
534 return this.getCurrentConfig().getShort(key, defaultValue);
535 }
536
537 @Override
538 public short getShort(String key)
539 {
540 return this.getCurrentConfig().getShort(key);
541 }
542
543 @Override
544 public String getString(String key, String defaultValue)
545 {
546 return this.getCurrentConfig().getString(key, defaultValue);
547 }
548
549 @Override
550 public String getString(String key)
551 {
552 return this.getCurrentConfig().getString(key);
553 }
554
555 @Override
556 public String[] getStringArray(String key)
557 {
558 return this.getCurrentConfig().getStringArray(key);
559 }
560
561 @Override
562 public boolean isEmpty()
563 {
564 return this.getCurrentConfig().isEmpty();
565 }
566
567 @Override
568 public void setProperty(String key, Object value)
569 {
570 if (configs != null)
571 {
572 this.getCurrentConfig().setProperty(key, value);
573 }
574 }
575
576 @Override
577 public Configuration subset(String prefix)
578 {
579 return this.getCurrentConfig().subset(prefix);
580 }
581
582 @Override
583 public Node getRoot()
584 {
585 return this.getCurrentConfig().getRoot();
586 }
587
588 @Override
589 public void setRoot(Node node)
590 {
591 if (configs != null)
592 {
593 this.getCurrentConfig().setRoot(node);
594 }
595 else
596 {
597 super.setRoot(node);
598 }
599 }
600
601 @Override
602 public ExpressionEngine getExpressionEngine()
603 {
604 return super.getExpressionEngine();
605 }
606
607 @Override
608 public void setExpressionEngine(ExpressionEngine expressionEngine)
609 {
610 super.setExpressionEngine(expressionEngine);
611 }
612
613 @Override
614 public void addNodes(String key, Collection<? extends ConfigurationNode> nodes)
615 {
616 this.getCurrentConfig().addNodes(key, nodes);
617 }
618
619 @Override
620 public SubnodeConfiguration configurationAt(String key, boolean supportUpdates)
621 {
622 return this.getCurrentConfig().configurationAt(key, supportUpdates);
623 }
624
625 @Override
626 public SubnodeConfiguration configurationAt(String key)
627 {
628 return this.getCurrentConfig().configurationAt(key);
629 }
630
631 @Override
632 public List<HierarchicalConfiguration> configurationsAt(String key)
633 {
634 return this.getCurrentConfig().configurationsAt(key);
635 }
636
637 @Override
638 public void clearTree(String key)
639 {
640 this.getCurrentConfig().clearTree(key);
641 }
642
643 @Override
644 public int getMaxIndex(String key)
645 {
646 return this.getCurrentConfig().getMaxIndex(key);
647 }
648
649 @Override
650 public Configuration interpolatedConfiguration()
651 {
652 return this.getCurrentConfig().interpolatedConfiguration();
653 }
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678 @Override
679 public Configuration getSource(String key)
680 {
681 if (key == null)
682 {
683 throw new IllegalArgumentException("Key must not be null!");
684 }
685 return getCurrentConfig().getSource(key);
686 }
687
688 @Override
689 public void addConfigurationListener(ConfigurationListener l)
690 {
691 super.addConfigurationListener(l);
692
693 for (CombinedConfiguration cc : configs.values())
694 {
695 cc.addConfigurationListener(l);
696 }
697 }
698
699 @Override
700 public boolean removeConfigurationListener(ConfigurationListener l)
701 {
702 for (CombinedConfiguration cc : configs.values())
703 {
704 cc.removeConfigurationListener(l);
705 }
706 return super.removeConfigurationListener(l);
707 }
708
709 @Override
710 public Collection<ConfigurationListener> getConfigurationListeners()
711 {
712 return super.getConfigurationListeners();
713 }
714
715 @Override
716 public void clearConfigurationListeners()
717 {
718 for (CombinedConfiguration cc : configs.values())
719 {
720 cc.clearConfigurationListeners();
721 }
722 super.clearConfigurationListeners();
723 }
724
725 @Override
726 public void addErrorListener(ConfigurationErrorListener l)
727 {
728 for (CombinedConfiguration cc : configs.values())
729 {
730 cc.addErrorListener(l);
731 }
732 super.addErrorListener(l);
733 }
734
735 @Override
736 public boolean removeErrorListener(ConfigurationErrorListener l)
737 {
738 for (CombinedConfiguration cc : configs.values())
739 {
740 cc.removeErrorListener(l);
741 }
742 return super.removeErrorListener(l);
743 }
744
745 @Override
746 public void clearErrorListeners()
747 {
748 for (CombinedConfiguration cc : configs.values())
749 {
750 cc.clearErrorListeners();
751 }
752 super.clearErrorListeners();
753 }
754
755 @Override
756 public Collection<ConfigurationErrorListener> getErrorListeners()
757 {
758 return super.getErrorListeners();
759 }
760
761
762
763
764
765
766
767
768
769
770 @Override
771 public Object clone()
772 {
773 return super.clone();
774 }
775
776
777
778
779
780
781
782
783
784 @Override
785 public void invalidate()
786 {
787 getCurrentConfig().invalidate();
788 }
789
790 public void invalidateAll()
791 {
792 if (configs == null)
793 {
794 return;
795 }
796 for (CombinedConfiguration cc : configs.values())
797 {
798 cc.invalidate();
799 }
800 }
801
802
803
804
805
806
807 @Override
808 protected Object resolveContainerStore(String key)
809 {
810 if (recursive.get().booleanValue())
811 {
812 return null;
813 }
814 recursive.set(Boolean.TRUE);
815 try
816 {
817 return super.resolveContainerStore(key);
818 }
819 finally
820 {
821 recursive.set(Boolean.FALSE);
822 }
823 }
824
825 private CombinedConfiguration getCurrentConfig()
826 {
827 String key = localSubst.replace(keyPattern);
828 CombinedConfiguration config = configs.get(key);
829
830 if (config == null)
831 {
832 synchronized (configs)
833 {
834 config = configs.get(key);
835 if (config == null)
836 {
837 config = new CombinedConfiguration(getNodeCombiner());
838 if (loggerName != null)
839 {
840 Log log = LogFactory.getLog(loggerName);
841 if (log != null)
842 {
843 config.setLogger(log);
844 }
845 }
846 config.setIgnoreReloadExceptions(isIgnoreReloadExceptions());
847 config.setExpressionEngine(this.getExpressionEngine());
848 config.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
849 config.setConversionExpressionEngine(getConversionExpressionEngine());
850 config.setListDelimiter(getListDelimiter());
851 for (ConfigurationErrorListener listener : getErrorListeners())
852 {
853 config.addErrorListener(listener);
854 }
855 for (ConfigurationListener listener : getConfigurationListeners())
856 {
857 config.addConfigurationListener(listener);
858 }
859 config.setForceReloadCheck(isForceReloadCheck());
860 for (ConfigData data : configurations)
861 {
862 config.addConfiguration(data.getConfiguration(), data.getName(), data.getAt());
863 }
864 configs.put(key, config);
865 }
866 }
867 }
868 if (getLogger().isDebugEnabled())
869 {
870 getLogger().debug("Returning config for " + key + ": " + config);
871 }
872 return config;
873 }
874
875
876
877
878 static class ConfigData
879 {
880
881 private AbstractConfiguration configuration;
882
883
884 private String name;
885
886
887 private String at;
888
889
890
891
892
893
894
895
896
897 public ConfigData(AbstractConfiguration config, String n, String at)
898 {
899 configuration = config;
900 name = n;
901 this.at = at;
902 }
903
904
905
906
907
908
909 public AbstractConfiguration getConfiguration()
910 {
911 return configuration;
912 }
913
914
915
916
917
918
919 public String getName()
920 {
921 return name;
922 }
923
924
925
926
927
928
929 public String getAt()
930 {
931 return at;
932 }
933
934 }
935 }