##### Coverage Report - org.apache.commons.configuration.DynamicCombinedConfiguration

Classes in this File | Line Coverage | Branch Coverage | Complexity
DynamicCombinedConfiguration |
24% | 45/185
38% | 9/24
| 1.3333333333333333;1,333
DynamicCombinedConfiguration$1 |
50% | 1/2
N/A | N/A
| 1.3333333333333333;1,333
DynamicCombinedConfiguration$ConfigData |
100% | 8/8
N/A | N/A
| 1.3333333333333333;1,333

1 |  |
     /*
2 |  |
      * Licensed to the Apache Software Foundation (ASF) under one or more
3 |  |
      * contributor license agreements.  See the NOTICE file distributed with
4 |  |
      * this work for additional information regarding copyright ownership.
5 |  |
      * The ASF licenses this file to You under the Apache License, Version 2.0
6 |  |
      * (the "License"); you may not use this file except in compliance with
7 |  |
      * the License.  You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      * Unless required by applicable law or agreed to in writing, software
12 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      * See the License for the specific language governing permissions and
15 |  |
      * limitations under the License.
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 |  |
30 |  |
     import org.apache.commons.configuration.event.ConfigurationErrorListener;
31 |  |
     import org.apache.commons.configuration.event.ConfigurationListener;
32 |  |
     import org.apache.commons.configuration.tree.ConfigurationNode;
33 |  |
     import org.apache.commons.configuration.tree.ExpressionEngine;
34 |  |
     import org.apache.commons.configuration.tree.NodeCombiner;
35 |  |
36 |  |
     /**
37 |  |
      * DynamicCombinedConfiguration allows a set of CombinedConfigurations to be used. Each CombinedConfiguration
38 |  |
      * is referenced by a key that is dynamically constructed from a key pattern on each call. The key pattern
39 |  |
      * will be resolved using the configured ConfigurationInterpolator.
40 |  |
      * @since 1.6
41 |  |
      * @author <a
42 |  |
      * href="http://commons.apache.org/configuration/team-list.html">Commons
43 |  |
      * Configuration team</a>
44 |  |
      * @version $Id: DynamicCombinedConfiguration.java 727955 2008-12-19 07:06:16Z oheger $
45 |  |
      */
46 |  |
     public class DynamicCombinedConfiguration extends CombinedConfiguration
47 |  |
     {
48 |  |
         /**
49 |  |
          * Prevent recursion while resolving unprefixed properties.
50 |  |
          */
51 | 1 |
         private static ThreadLocal recursive = new ThreadLocal()
52 |  |
         {
53 | 1 |
             protected synchronized Object initialValue()
54 |  |
             {
55 | 0 |
                 return Boolean.FALSE;
56 |  |
             }
57 |  |
         };
58 |  |
59 |  |
         /** The CombinedConfigurations */
60 | 1 |
         private Map configs = new HashMap();
61 |  |
62 |  |
         /** Stores a list with the contained configurations. */
63 | 1 |
         private List configurations = new ArrayList();
64 |  |
65 |  |
         /** Stores a map with the named configurations. */
66 | 1 |
         private Map namedConfigurations = new HashMap();
67 |  |
68 |  |
         /** The key pattern for the CombinedConfiguration map */
69 |  |
         private String keyPattern;
70 |  |
71 |  |
         /** Stores the combiner. */
72 |  |
         private NodeCombiner nodeCombiner;
73 |  |
74 |  |
         /**
75 |  |
          * Creates a new instance of <code>CombinedConfiguration</code> and
76 |  |
          * initializes the combiner to be used.
77 |  |
          *
78 |  |
          * @param comb the node combiner (can be <b>null</b>, then a union combiner
79 |  |
          * is used as default)
80 |  |
          */
81 |  |
         public DynamicCombinedConfiguration(NodeCombiner comb)
82 |  |
         {
83 | 0 |
             super();
84 | 0 |
             setNodeCombiner(comb);
85 | 0 |
         }
86 |  |
87 |  |
         /**
88 |  |
          * Creates a new instance of <code>CombinedConfiguration</code> that uses
89 |  |
          * a union combiner.
90 |  |
          *
91 |  |
          * @see org.apache.commons.configuration.tree.UnionCombiner
92 |  |
          */
93 |  |
         public DynamicCombinedConfiguration()
94 |  |
         {
95 | 1 |
             super();
96 | 1 |
         }
97 |  |
98 |  |
         public void setKeyPattern(String pattern)
99 |  |
         {
100 | 1 |
             this.keyPattern = pattern;
101 | 1 |
         }
102 |  |
103 |  |
         public String getKeyPattern()
104 |  |
         {
105 | 0 |
             return this.keyPattern;
106 |  |
         }
107 |  |
108 |  |
         /**
109 |  |
          * Returns the node combiner that is used for creating the combined node
110 |  |
          * structure.
111 |  |
          *
112 |  |
          * @return the node combiner
113 |  |
          */
114 |  |
         public NodeCombiner getNodeCombiner()
115 |  |
         {
116 | 8 |
             return nodeCombiner;
117 |  |
         }
118 |  |
119 |  |
         /**
120 |  |
          * Sets the node combiner. This object will be used when the combined node
121 |  |
          * structure is to be constructed. It must not be <b>null</b>, otherwise an
122 |  |
          * <code>IllegalArgumentException</code> exception is thrown. Changing the
123 |  |
          * node combiner causes an invalidation of this combined configuration, so
124 |  |
          * that the new combiner immediately takes effect.
125 |  |
          *
126 |  |
          * @param nodeCombiner the node combiner
127 |  |
          */
128 |  |
         public void setNodeCombiner(NodeCombiner nodeCombiner)
129 |  |
         {
130 | 1 |
             if (nodeCombiner == null)
131 |  |
             {
132 | 0 |
                 throw new IllegalArgumentException(
133 |  |
                         "Node combiner must not be null!");
134 |  |
             }
135 | 1 |
             this.nodeCombiner = nodeCombiner;
136 | 1 |
             invalidateAll();
137 | 1 |
         }
138 |  |
         /**
139 |  |
          * Adds a new configuration to this combined configuration. It is possible
140 |  |
          * (but not mandatory) to give the new configuration a name. This name must
141 |  |
          * be unique, otherwise a <code>ConfigurationRuntimeException</code> will
142 |  |
          * be thrown. With the optional <code>at</code> argument you can specify
143 |  |
          * where in the resulting node structure the content of the added
144 |  |
          * configuration should appear. This is a string that uses dots as property
145 |  |
          * delimiters (independent on the current expression engine). For instance
146 |  |
          * if you pass in the string <code>&quot;database.tables&quot;</code>,
147 |  |
          * all properties of the added configuration will occur in this branch.
148 |  |
          *
149 |  |
          * @param config the configuration to add (must not be <b>null</b>)
150 |  |
          * @param name the name of this configuration (can be <b>null</b>)
151 |  |
          * @param at the position of this configuration in the combined tree (can be
152 |  |
          * <b>null</b>)
153 |  |
          */
154 |  |
         public void addConfiguration(AbstractConfiguration config, String name,
155 |  |
                 String at)
156 |  |
         {
157 | 2 |
             ConfigData cd = new ConfigData(config, name, at);
158 | 2 |
             configurations.add(cd);
159 | 2 |
             if (name != null)
160 |  |
             {
161 | 2 |
                 namedConfigurations.put(name, config);
162 |  |
             }
163 | 2 |
         }
164 |  |
            /**
165 |  |
          * Returns the number of configurations that are contained in this combined
166 |  |
          * configuration.
167 |  |
          *
168 |  |
          * @return the number of contained configurations
169 |  |
          */
170 |  |
         public int getNumberOfConfigurations()
171 |  |
         {
172 | 0 |
             return configurations.size();
173 |  |
         }
174 |  |
175 |  |
         /**
176 |  |
          * Returns the configuration at the specified index. The contained
177 |  |
          * configurations are numbered in the order they were added to this combined
178 |  |
          * configuration. The index of the first configuration is 0.
179 |  |
          *
180 |  |
          * @param index the index
181 |  |
          * @return the configuration at this index
182 |  |
          */
183 |  |
         public Configuration getConfiguration(int index)
184 |  |
         {
185 | 0 |
             ConfigData cd = (ConfigData) configurations.get(index);
186 | 0 |
             return cd.getConfiguration();
187 |  |
         }
188 |  |
189 |  |
         /**
190 |  |
          * Returns the configuration with the given name. This can be <b>null</b>
191 |  |
          * if no such configuration exists.
192 |  |
          *
193 |  |
          * @param name the name of the configuration
194 |  |
          * @return the configuration with this name
195 |  |
          */
196 |  |
         public Configuration getConfiguration(String name)
197 |  |
         {
198 | 0 |
             return (Configuration) namedConfigurations.get(name);
199 |  |
         }
200 |  |
201 |  |
         /**
202 |  |
          * Returns a set with the names of all configurations contained in this
203 |  |
          * combined configuration. Of course here are only these configurations
204 |  |
          * listed, for which a name was specified when they were added.
205 |  |
          *
206 |  |
          * @return a set with the names of the contained configurations (never
207 |  |
          * <b>null</b>)
208 |  |
          */
209 |  |
         public Set getConfigurationNames()
210 |  |
         {
211 | 0 |
             return namedConfigurations.keySet();
212 |  |
         }
213 |  |
214 |  |
         /**
215 |  |
          * Removes the configuration with the specified name.
216 |  |
          *
217 |  |
          * @param name the name of the configuration to be removed
218 |  |
          * @return the removed configuration (<b>null</b> if this configuration
219 |  |
          * was not found)
220 |  |
          */
221 |  |
         public Configuration removeConfiguration(String name)
222 |  |
         {
223 | 0 |
             Configuration conf = getConfiguration(name);
224 | 0 |
             if (conf != null)
225 |  |
             {
226 | 0 |
                 removeConfiguration(conf);
227 |  |
             }
228 | 0 |
             return conf;
229 |  |
         }
230 |  |
231 |  |
         /**
232 |  |
          * Removes the specified configuration from this combined configuration.
233 |  |
          *
234 |  |
          * @param config the configuration to be removed
235 |  |
          * @return a flag whether this configuration was found and could be removed
236 |  |
          */
237 |  |
         public boolean removeConfiguration(Configuration config)
238 |  |
         {
239 | 0 |
             for (int index = 0; index < getNumberOfConfigurations(); index++)
240 |  |
             {
241 | 0 |
                 if (((ConfigData) configurations.get(index)).getConfiguration() == config)
242 |  |
                 {
243 | 0 |
                     removeConfigurationAt(index);
244 |  |
245 |  |
                 }
246 |  |
             }
247 |  |
248 | 0 |
             return super.removeConfiguration(config);
249 |  |
         }
250 |  |
251 |  |
         /**
252 |  |
          * Removes the configuration at the specified index.
253 |  |
          *
254 |  |
          * @param index the index
255 |  |
          * @return the removed configuration
256 |  |
          */
257 |  |
         public Configuration removeConfigurationAt(int index)
258 |  |
         {
259 | 0 |
             ConfigData cd = (ConfigData) configurations.remove(index);
260 | 0 |
             if (cd.getName() != null)
261 |  |
             {
262 | 0 |
                 namedConfigurations.remove(cd.getName());
263 |  |
             }
264 | 0 |
             return super.removeConfigurationAt(index);
265 |  |
         }
266 |  |
         /**
267 |  |
          * Returns the configuration root node of this combined configuration. This
268 |  |
          * method will construct a combined node structure using the current node
269 |  |
          * combiner if necessary.
270 |  |
          *
271 |  |
          * @return the combined root node
272 |  |
          */
273 |  |
         public ConfigurationNode getRootNode()
274 |  |
         {
275 | 0 |
             return getCurrentConfig().getRootNode();
276 |  |
         }
277 |  |
278 |  |
         public void setRootNode(ConfigurationNode rootNode)
279 |  |
         {
280 | 1 |
             if (configs != null)
281 |  |
             {
282 | 0 |
                 this.getCurrentConfig().setRootNode(rootNode);
283 |  |
             }
284 |  |
             else
285 |  |
             {
286 | 1 |
                 super.setRootNode(rootNode);
287 |  |
             }
288 | 1 |
         }
289 |  |
290 |  |
         public void addProperty(String key, Object value)
291 |  |
         {
292 | 0 |
             this.getCurrentConfig().addProperty(key, value);
293 | 0 |
         }
294 |  |
295 |  |
         public void clear()
296 |  |
         {
297 | 1 |
             if (configs != null)
298 |  |
             {
299 | 0 |
                 this.getCurrentConfig().clear();
300 |  |
             }
301 | 1 |
         }
302 |  |
303 |  |
         public void clearProperty(String key)
304 |  |
         {
305 | 0 |
             this.getCurrentConfig().clearProperty(key);
306 | 0 |
         }
307 |  |
308 |  |
         public boolean containsKey(String key)
309 |  |
         {
310 | 0 |
             return this.getCurrentConfig().containsKey(key);
311 |  |
         }
312 |  |
313 |  |
         public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)
314 |  |
         {
315 | 0 |
             return this.getCurrentConfig().getBigDecimal(key, defaultValue);
316 |  |
         }
317 |  |
318 |  |
         public BigDecimal getBigDecimal(String key)
319 |  |
         {
320 | 0 |
             return this.getCurrentConfig().getBigDecimal(key);
321 |  |
         }
322 |  |
323 |  |
         public BigInteger getBigInteger(String key, BigInteger defaultValue)
324 |  |
         {
325 | 0 |
             return this.getCurrentConfig().getBigInteger(key, defaultValue);
326 |  |
         }
327 |  |
328 |  |
         public BigInteger getBigInteger(String key)
329 |  |
         {
330 | 0 |
             return this.getCurrentConfig().getBigInteger(key);
331 |  |
         }
332 |  |
333 |  |
         public boolean getBoolean(String key, boolean defaultValue)
334 |  |
         {
335 | 0 |
             return this.getCurrentConfig().getBoolean(key, defaultValue);
336 |  |
         }
337 |  |
338 |  |
         public Boolean getBoolean(String key, Boolean defaultValue)
339 |  |
         {
340 | 0 |
             return this.getCurrentConfig().getBoolean(key, defaultValue);
341 |  |
         }
342 |  |
343 |  |
         public boolean getBoolean(String key)
344 |  |
         {
345 | 0 |
             return this.getCurrentConfig().getBoolean(key);
346 |  |
         }
347 |  |
348 |  |
         public byte getByte(String key, byte defaultValue)
349 |  |
         {
350 | 0 |
             return this.getCurrentConfig().getByte(key, defaultValue);
351 |  |
         }
352 |  |
353 |  |
         public Byte getByte(String key, Byte defaultValue)
354 |  |
         {
355 | 0 |
             return this.getCurrentConfig().getByte(key, defaultValue);
356 |  |
         }
357 |  |
358 |  |
         public byte getByte(String key)
359 |  |
         {
360 | 0 |
             return this.getCurrentConfig().getByte(key);
361 |  |
         }
362 |  |
363 |  |
         public double getDouble(String key, double defaultValue)
364 |  |
         {
365 | 0 |
             return this.getCurrentConfig().getDouble(key, defaultValue);
366 |  |
         }
367 |  |
368 |  |
         public Double getDouble(String key, Double defaultValue)
369 |  |
         {
370 | 0 |
             return this.getCurrentConfig().getDouble(key, defaultValue);
371 |  |
         }
372 |  |
373 |  |
         public double getDouble(String key)
374 |  |
         {
375 | 0 |
             return this.getCurrentConfig().getDouble(key);
376 |  |
         }
377 |  |
378 |  |
         public float getFloat(String key, float defaultValue)
379 |  |
         {
380 | 0 |
             return this.getCurrentConfig().getFloat(key, defaultValue);
381 |  |
         }
382 |  |
383 |  |
         public Float getFloat(String key, Float defaultValue)
384 |  |
         {
385 | 0 |
             return this.getCurrentConfig().getFloat(key, defaultValue);
386 |  |
         }
387 |  |
388 |  |
         public float getFloat(String key)
389 |  |
         {
390 | 0 |
             return this.getCurrentConfig().getFloat(key);
391 |  |
         }
392 |  |
393 |  |
         public int getInt(String key, int defaultValue)
394 |  |
         {
395 | 0 |
             return this.getCurrentConfig().getInt(key, defaultValue);
396 |  |
         }
397 |  |
398 |  |
         public int getInt(String key)
399 |  |
         {
400 | 4 |
             return this.getCurrentConfig().getInt(key);
401 |  |
         }
402 |  |
403 |  |
         public Integer getInteger(String key, Integer defaultValue)
404 |  |
         {
405 | 0 |
             return this.getCurrentConfig().getInteger(key, defaultValue);
406 |  |
         }
407 |  |
408 |  |
         public Iterator getKeys()
409 |  |
         {
410 | 0 |
             return this.getCurrentConfig().getKeys();
411 |  |
         }
412 |  |
413 |  |
         public Iterator getKeys(String prefix)
414 |  |
         {
415 | 0 |
             return this.getCurrentConfig().getKeys(prefix);
416 |  |
         }
417 |  |
418 |  |
         public List getList(String key, List defaultValue)
419 |  |
         {
420 | 0 |
             return this.getCurrentConfig().getList(key, defaultValue);
421 |  |
         }
422 |  |
423 |  |
         public List getList(String key)
424 |  |
         {
425 | 0 |
             return this.getCurrentConfig().getList(key);
426 |  |
         }
427 |  |
428 |  |
         public long getLong(String key, long defaultValue)
429 |  |
         {
430 | 0 |
             return this.getCurrentConfig().getLong(key, defaultValue);
431 |  |
         }
432 |  |
433 |  |
         public Long getLong(String key, Long defaultValue)
434 |  |
         {
435 | 0 |
             return this.getCurrentConfig().getLong(key, defaultValue);
436 |  |
         }
437 |  |
438 |  |
         public long getLong(String key)
439 |  |
         {
440 | 0 |
             return this.getCurrentConfig().getLong(key);
441 |  |
         }
442 |  |
443 |  |
         public Properties getProperties(String key)
444 |  |
         {
445 | 0 |
             return this.getCurrentConfig().getProperties(key);
446 |  |
         }
447 |  |
448 |  |
         public Object getProperty(String key)
449 |  |
         {
450 | 0 |
             return this.getCurrentConfig().getProperty(key);
451 |  |
         }
452 |  |
453 |  |
         public short getShort(String key, short defaultValue)
454 |  |
         {
455 | 0 |
             return this.getCurrentConfig().getShort(key, defaultValue);
456 |  |
         }
457 |  |
458 |  |
         public Short getShort(String key, Short defaultValue)
459 |  |
         {
460 | 0 |
             return this.getCurrentConfig().getShort(key, defaultValue);
461 |  |
         }
462 |  |
463 |  |
         public short getShort(String key)
464 |  |
         {
465 | 0 |
             return this.getCurrentConfig().getShort(key);
466 |  |
         }
467 |  |
468 |  |
         public String getString(String key, String defaultValue)
469 |  |
         {
470 | 0 |
             return this.getCurrentConfig().getString(key, defaultValue);
471 |  |
         }
472 |  |
473 |  |
         public String getString(String key)
474 |  |
         {
475 | 0 |
             return this.getCurrentConfig().getString(key);
476 |  |
         }
477 |  |
478 |  |
         public String[] getStringArray(String key)
479 |  |
         {
480 | 0 |
             return this.getCurrentConfig().getStringArray(key);
481 |  |
         }
482 |  |
483 |  |
         public boolean isEmpty()
484 |  |
         {
485 | 0 |
             return this.getCurrentConfig().isEmpty();
486 |  |
         }
487 |  |
488 |  |
         public void setProperty(String key, Object value)
489 |  |
         {
490 | 0 |
             if (configs != null)
491 |  |
             {
492 | 0 |
                 this.getCurrentConfig().setProperty(key, value);
493 |  |
             }
494 | 0 |
         }
495 |  |
496 |  |
         public Configuration subset(String prefix)
497 |  |
         {
498 | 0 |
             return this.getCurrentConfig().subset(prefix);
499 |  |
         }
500 |  |
501 |  |
         public Node getRoot()
502 |  |
         {
503 | 0 |
             return this.getCurrentConfig().getRoot();
504 |  |
         }
505 |  |
506 |  |
         public void setRoot(Node node)
507 |  |
         {
508 | 0 |
             if (configs != null)
509 |  |
             {
510 | 0 |
                 this.getCurrentConfig().setRoot(node);
511 |  |
             }
512 |  |
             else
513 |  |
             {
514 | 0 |
                 super.setRoot(node);
515 |  |
             }
516 | 0 |
         }
517 |  |
518 |  |
         public ExpressionEngine getExpressionEngine()
519 |  |
         {
520 | 4 |
             return super.getExpressionEngine();
521 |  |
         }
522 |  |
523 |  |
         public void setExpressionEngine(ExpressionEngine expressionEngine)
524 |  |
         {
525 | 0 |
             super.setExpressionEngine(expressionEngine);
526 | 0 |
         }
527 |  |
528 |  |
         public void addNodes(String key, Collection nodes)
529 |  |
         {
530 | 0 |
             this.getCurrentConfig().addNodes(key, nodes);
531 | 0 |
         }
532 |  |
533 |  |
         public SubnodeConfiguration configurationAt(String key, boolean supportUpdates)
534 |  |
         {
535 | 0 |
             return this.getCurrentConfig().configurationAt(key, supportUpdates);
536 |  |
         }
537 |  |
538 |  |
         public SubnodeConfiguration configurationAt(String key)
539 |  |
         {
540 | 0 |
             return this.getCurrentConfig().configurationAt(key);
541 |  |
         }
542 |  |
543 |  |
         public List configurationsAt(String key)
544 |  |
         {
545 | 0 |
             return this.getCurrentConfig().configurationsAt(key);
546 |  |
         }
547 |  |
548 |  |
         public void clearTree(String key)
549 |  |
         {
550 | 0 |
             this.getCurrentConfig().clearTree(key);
551 | 0 |
         }
552 |  |
553 |  |
         public int getMaxIndex(String key)
554 |  |
         {
555 | 0 |
             return this.getCurrentConfig().getMaxIndex(key);
556 |  |
         }
557 |  |
558 |  |
         public Configuration interpolatedConfiguration()
559 |  |
         {
560 | 0 |
             return this.getCurrentConfig().interpolatedConfiguration();
561 |  |
         }
562 |  |
563 |  |
564 |  |
         /**
565 |  |
          * Returns the configuration source, in which the specified key is defined.
566 |  |
          * This method will determine the configuration node that is identified by
567 |  |
          * the given key. The following constellations are possible:
568 |  |
          * <ul>
569 |  |
          * <li>If no node object is found for this key, <b>null</b> is returned.</li>
570 |  |
          * <li>If the key maps to multiple nodes belonging to different
571 |  |
          * configuration sources, a <code>IllegalArgumentException</code> is
572 |  |
          * thrown (in this case no unique source can be determined).</li>
573 |  |
          * <li>If exactly one node is found for the key, the (child) configuration
574 |  |
          * object, to which the node belongs is determined and returned.</li>
575 |  |
          * <li>For keys that have been added directly to this combined
576 |  |
          * configuration and that do not belong to the namespaces defined by
577 |  |
          * existing child configurations this configuration will be returned.</li>
578 |  |
          * </ul>
579 |  |
          *
580 |  |
          * @param key the key of a configuration property
581 |  |
          * @return the configuration, to which this property belongs or <b>null</b>
582 |  |
          * if the key cannot be resolved
583 |  |
          * @throws IllegalArgumentException if the key maps to multiple properties
584 |  |
          * and the source cannot be determined, or if the key is <b>null</b>
585 |  |
          */
586 |  |
         public Configuration getSource(String key)
587 |  |
         {
588 | 0 |
             if (key == null)
589 |  |
             {
590 | 0 |
                 throw new IllegalArgumentException("Key must not be null!");
591 |  |
             }
592 | 0 |
             return getCurrentConfig().getSource(key);
593 |  |
         }
594 |  |
595 |  |
         public void addConfigurationListener(ConfigurationListener l)
596 |  |
         {
597 | 0 |
             super.addConfigurationListener(l);
598 |  |
599 | 0 |
             Iterator iter = configs.values().iterator();
600 | 0 |
             while (iter.hasNext())
601 |  |
             {
602 | 0 |
                 CombinedConfiguration config = (CombinedConfiguration) iter.next();
603 | 0 |
                 config.addConfigurationListener(l);
604 |  |
             }
605 | 0 |
         }
606 |  |
607 |  |
         public boolean removeConfigurationListener(ConfigurationListener l)
608 |  |
         {
609 | 0 |
             Iterator iter = configs.values().iterator();
610 | 0 |
             while (iter.hasNext())
611 |  |
             {
612 | 0 |
                 CombinedConfiguration config = (CombinedConfiguration) iter.next();
613 | 0 |
                 config.removeConfigurationListener(l);
614 |  |
             }
615 | 0 |
             return super.removeConfigurationListener(l);
616 |  |
         }
617 |  |
618 |  |
         public Collection getConfigurationListeners()
619 |  |
         {
620 | 0 |
             return super.getConfigurationListeners();
621 |  |
         }
622 |  |
623 |  |
         public void clearConfigurationListeners()
624 |  |
         {
625 | 0 |
             Iterator iter = configs.values().iterator();
626 | 0 |
             while (iter.hasNext())
627 |  |
             {
628 | 0 |
                 CombinedConfiguration config = (CombinedConfiguration) iter.next();
629 | 0 |
                 config.clearConfigurationListeners();
630 |  |
             }
631 | 0 |
             super.clearConfigurationListeners();
632 | 0 |
         }
633 |  |
634 |  |
         public void addErrorListener(ConfigurationErrorListener l)
635 |  |
         {
636 | 0 |
             Iterator iter = configs.values().iterator();
637 | 0 |
             while (iter.hasNext())
638 |  |
             {
639 | 0 |
                 CombinedConfiguration config = (CombinedConfiguration) iter.next();
640 | 0 |
                 config.addErrorListener(l);
641 |  |
             }
642 | 0 |
             super.addErrorListener(l);
643 | 0 |
         }
644 |  |
645 |  |
         public boolean removeErrorListener(ConfigurationErrorListener l)
646 |  |
         {
647 | 0 |
             Iterator iter = configs.values().iterator();
648 | 0 |
             while (iter.hasNext())
649 |  |
             {
650 | 0 |
                 CombinedConfiguration config = (CombinedConfiguration) iter.next();
651 | 0 |
                 config.removeErrorListener(l);
652 |  |
             }
653 | 0 |
             return super.removeErrorListener(l);
654 |  |
         }
655 |  |
656 |  |
         public void clearErrorListeners()
657 |  |
         {
658 | 0 |
             Iterator iter = configs.values().iterator();
659 | 0 |
             while (iter.hasNext())
660 |  |
             {
661 | 0 |
                 CombinedConfiguration config = (CombinedConfiguration) iter.next();
662 | 0 |
                 config.clearErrorListeners();
663 |  |
             }
664 | 0 |
             super.clearErrorListeners();
665 | 0 |
         }
666 |  |
667 |  |
         public Collection getErrorListeners()
668 |  |
         {
669 | 0 |
             return super.getErrorListeners();
670 |  |
         }
671 |  |
672 |  |
673 |  |
674 |  |
         /**
675 |  |
          * Returns a copy of this object. This implementation performs a deep clone,
676 |  |
          * i.e. all contained configurations will be cloned, too. For this to work,
677 |  |
          * all contained configurations must be cloneable. Registered event
678 |  |
          * listeners won't be cloned. The clone will use the same node combiner than
679 |  |
          * the original.
680 |  |
          *
681 |  |
          * @return the copied object
682 |  |
          */
683 |  |
         public Object clone()
684 |  |
         {
685 | 0 |
             return super.clone();
686 |  |
         }
687 |  |
688 |  |
689 |  |
690 |  |
         /**
691 |  |
          * Invalidates the current combined configuration. This means that the next time a
692 |  |
          * property is accessed the combined node structure must be re-constructed.
693 |  |
          * Invalidation of a combined configuration also means that an event of type
694 |  |
          * <code>EVENT_COMBINED_INVALIDATE</code> is fired. Note that while other
695 |  |
          * events most times appear twice (once before and once after an update),
696 |  |
          * this event is only fired once (after update).
697 |  |
          */
698 |  |
         public void invalidate()
699 |  |
         {
700 | 0 |
             getCurrentConfig().invalidate();
701 | 0 |
         }
702 |  |
703 |  |
         public void invalidateAll()
704 |  |
         {
705 | 1 |
             if (configs == null)
706 |  |
             {
707 | 1 |
                 return;
708 |  |
             }
709 | 0 |
             Iterator iter = configs.values().iterator();
710 | 0 |
             while (iter.hasNext())
711 |  |
             {
712 | 0 |
                CombinedConfiguration config = (CombinedConfiguration) iter.next();
713 | 0 |
                config.invalidate();
714 |  |
             }
715 | 0 |
         }
716 |  |
717 |  |
         /*
718 |  |
          * Don't allow resolveContainerStore to be called recursively.
719 |  |
          * @param key The key to resolve.
720 |  |
          * @return The value of the key.
721 |  |
          */
722 |  |
         protected Object resolveContainerStore(String key)
723 |  |
         {
724 | 0 |
             if (((Boolean) recursive.get()).booleanValue())
725 |  |
             {
726 | 0 |
                 return null;
727 |  |
             }
728 | 0 |
             recursive.set(Boolean.TRUE);
729 |  |
             try
730 |  |
             {
731 | 0 |
                 return super.resolveContainerStore(key);
732 |  |
             }
733 |  |
             finally
734 |  |
             {
735 | 0 |
                 recursive.set(Boolean.FALSE);
736 |  |
             }
737 |  |
         }
738 |  |
739 |  |
         private CombinedConfiguration getCurrentConfig()
740 |  |
         {
741 | 4 |
             String key = getSubstitutor().replace(keyPattern);
742 |  |
             CombinedConfiguration config;
743 | 4 |
             synchronized (getNodeCombiner())
744 |  |
             {
745 | 4 |
                 config = (CombinedConfiguration) configs.get(key);
746 | 4 |
                 if (config == null)
747 |  |
                 {
748 | 4 |
                     config = new CombinedConfiguration(getNodeCombiner());
749 | 4 |
                     config.setExpressionEngine(this.getExpressionEngine());
750 | 4 |
                     Iterator iter = config.getErrorListeners().iterator();
751 | 4 |
                     while (iter.hasNext())
752 |  |
                     {
753 | 0 |
                         ConfigurationErrorListener listener = (ConfigurationErrorListener) iter.next();
754 | 0 |
                         config.addErrorListener(listener);
755 |  |
                     }
756 | 4 |
                     iter = config.getConfigurationListeners().iterator();
757 | 4 |
                     while (iter.hasNext())
758 |  |
                     {
759 | 0 |
                         ConfigurationListener listener = (ConfigurationListener) iter.next();
760 | 0 |
                         config.addConfigurationListener(listener);
761 |  |
                     }
762 | 4 |
                     config.setForceReloadCheck(isForceReloadCheck());
763 | 4 |
                     iter = configurations.iterator();
764 | 12 |
                     while (iter.hasNext())
765 |  |
                     {
766 | 8 |
                         ConfigData data = (ConfigData) iter.next();
767 | 8 |
                         config.addConfiguration(data.getConfiguration(), data.getName(),
768 |  |
                                 data.getAt());
769 |  |
                     }
770 | 4 |
                     configs.put(key, config);
771 |  |
                 }
772 | 4 |
             }
773 | 4 |
             return config;
774 |  |
         }
775 |  |
776 |  |
         /**
777 |  |
          * Internal class that identifies each Configuration.
778 |  |
          */
779 |  |
         static class ConfigData
780 |  |
         {
781 |  |
             /** Stores a reference to the configuration. */
782 |  |
             private AbstractConfiguration configuration;
783 |  |
784 |  |
             /** Stores the name under which the configuration is stored. */
785 |  |
             private String name;
786 |  |
787 |  |
             /** Stores the at string.*/
788 |  |
             private String at;
789 |  |
790 |  |
                     /**
791 |  |
              * Creates a new instance of <code>ConfigData</code> and initializes
792 |  |
              * it.
793 |  |
              *
794 |  |
              * @param config the configuration
795 |  |
              * @param n the name
796 |  |
              * @param at the at position
797 |  |
              */
798 |  |
             public ConfigData(AbstractConfiguration config, String n, String at)
799 | 2 |
             {
800 | 2 |
                 configuration = config;
801 | 2 |
                 name = n;
802 | 2 |
                 this.at = at;
803 | 2 |
             }
804 |  |
805 |  |
                     /**
806 |  |
              * Returns the stored configuration.
807 |  |
              *
808 |  |
              * @return the configuration
809 |  |
              */
810 |  |
             public AbstractConfiguration getConfiguration()
811 |  |
             {
812 | 8 |
                 return configuration;
813 |  |
             }
814 |  |
815 |  |
             /**
816 |  |
              * Returns the configuration's name.
817 |  |
              *
818 |  |
              * @return the name
819 |  |
              */
820 |  |
             public String getName()
821 |  |
             {
822 | 8 |
                 return name;
823 |  |
             }
824 |  |
825 |  |
             /**
826 |  |
              * Returns the at position of this configuration.
827 |  |
              *
828 |  |
              * @return the at position
829 |  |
              */
830 |  |
             public String getAt()
831 |  |
             {
832 | 8 |
                 return at;
833 |  |
             }
834 |  |
835 |  |
         }
836 |  |
     }