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

Classes in this File | Line Coverage | Branch Coverage | Complexity
DefaultConfigurationBuilder |
100% | 76/76
100% | 12/12
| 1.6666666666666667;1,667
DefaultConfigurationBuilder$ConfigurationBeanFactory |
100% | 12/12
100% | 3/3
| 1.6666666666666667;1,667
DefaultConfigurationBuilder$ConfigurationBuilderProvider |
100% | 5/5
100% | 1/1
| 1.6666666666666667;1,667
DefaultConfigurationBuilder$ConfigurationDeclaration |
100% | 16/16
100% | 4/4
| 1.6666666666666667;1,667
DefaultConfigurationBuilder$ConfigurationProvider |
100% | 9/9
N/A | N/A
| 1.6666666666666667;1,667
DefaultConfigurationBuilder$FileConfigurationProvider |
100% | 11/11
N/A | N/A
| 1.6666666666666667;1,667
DefaultConfigurationBuilder$FileExtensionConfigurationProvider |
100% | 9/9
100% | 1/1
| 1.6666666666666667;1,667

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.io.File;
20 |  |
     import java.net.URL;
21 |  |
     import java.util.HashMap;
22 |  |
     import java.util.Iterator;
23 |  |
     import java.util.List;
24 |  |
     import java.util.Map;
25 |  |
26 |  |
     import org.apache.commons.configuration.beanutils.BeanDeclaration;
27 |  |
     import org.apache.commons.configuration.beanutils.BeanFactory;
28 |  |
     import org.apache.commons.configuration.beanutils.BeanHelper;
29 |  |
     import org.apache.commons.configuration.beanutils.DefaultBeanFactory;
30 |  |
     import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;
31 |  |
     import org.apache.commons.configuration.plist.PropertyListConfiguration;
32 |  |
     import org.apache.commons.configuration.plist.XMLPropertyListConfiguration;
33 |  |
     import org.apache.commons.configuration.tree.ConfigurationNode;
34 |  |
     import org.apache.commons.configuration.tree.DefaultExpressionEngine;
35 |  |
     import org.apache.commons.configuration.tree.OverrideCombiner;
36 |  |
     import org.apache.commons.configuration.tree.UnionCombiner;
37 |  |
     import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
38 |  |
39 |  |
     /**
40 |  |
      * <p>
41 |  |
      * A factory class that creates a composite configuration from an XML based
42 |  |
      * <em>configuration definition file</em>.
43 |  |
      * </p>
44 |  |
      * <p>
45 |  |
      * This class provides an easy and flexible means for loading multiple
46 |  |
      * configuration sources and combining the results into a single configuration
47 |  |
      * object. The sources to be loaded are defined in an XML document that can
48 |  |
      * contain certain tags representing the different supported configuration
49 |  |
      * classes. If such a tag is found, the corresponding <code>Configuration</code>
50 |  |
      * class is instantiated and initialized using the classes of the
51 |  |
      * <code>beanutils</code> package (namely
52 |  |
      * <code>{@link org.apache.commons.configuration.beanutils.XMLBeanDeclaration XMLBeanDeclaration}</code>
53 |  |
      * will be used to extract the configuration's initialization parameters, which
54 |  |
      * allows for complex initialization szenarios).
55 |  |
      * </p>
56 |  |
      * <p>
57 |  |
      * It is also possible to add custom tags to the configuration definition file.
58 |  |
      * For this purpose register your own <code>ConfigurationProvider</code>
59 |  |
      * implementation for your tag using the <code>addConfigurationProvider()</code>
60 |  |
      * method. This provider will then be called when the corresponding custom tag
61 |  |
      * is detected. For the default configuration classes providers are already
62 |  |
      * registered.
63 |  |
      * </p>
64 |  |
      * <p>
65 |  |
      * The configuration definition file has the following basic structure:
66 |  |
      * </p>
67 |  |
      * <p>
68 |  |
      *
69 |  |
      * <pre>
70 |  |
      * &lt;configuration&gt;
71 |  |
      *   &lt;header&gt;
72 |  |
      *     &lt;!-- Optional meta information about the composite configuration --&gt;
73 |  |
      *   &lt;/header&gt;
74 |  |
      *   &lt;override&gt;
75 |  |
      *     &lt;!-- Declarations for override configurations --&gt;
76 |  |
      *   &lt;/override&gt;
77 |  |
      *   &lt;additional&gt;
78 |  |
      *     &lt;!-- Declarations for union configurations --&gt;
79 |  |
      *   &lt;/additional&gt;
80 |  |
      * &lt;/configuration&gt;
81 |  |
      * </pre>
82 |  |
      *
83 |  |
      * </p>
84 |  |
      * <p>
85 |  |
      * The name of the root element (here <code>configuration</code>) is
86 |  |
      * arbitrary. There are two sections (both of them are optional) for declaring
87 |  |
      * <em>override</em> and <em>additional</em> configurations. Configurations
88 |  |
      * in the former section are evaluated in the order of their declaration, and
89 |  |
      * properties of configurations declared earlier hide those of configurations
90 |  |
      * declared later. Configurations in the latter section are combined to a union
91 |  |
      * configuration, i.e. all of their properties are added to a large hierarchical
92 |  |
      * configuration. Configuration declarations that occur as direct children of
93 |  |
      * the root element are treated as override declarations.
94 |  |
      * </p>
95 |  |
      * <p>
96 |  |
      * Each configuration declaration consists of a tag whose name is associated
97 |  |
      * with a <code>ConfigurationProvider</code>. This can be one of the
98 |  |
      * pre-defined tags like <code>properties</code>, or <code>xml</code>, or
99 |  |
      * a custom tag, for which a configuration provider was registered. Attributes
100 |  |
      * and sub elements with specific initialization parameters can be added. There
101 |  |
      * are some reserved attributes with a special meaning that can be used in every
102 |  |
      * configuration declaration:
103 |  |
      * </p>
104 |  |
      * <p>
105 |  |
      * <table border="1">
106 |  |
      * <tr>
107 |  |
      * <th>Attribute</th>
108 |  |
      * <th>Meaning</th>
109 |  |
      * </tr>
110 |  |
      * <tr>
111 |  |
      * <td valign="top"><code>config-name</code></td>
112 |  |
      * <td>Allows to specify a name for this configuration. This name can be used
113 |  |
      * to obtain a reference to the configuration from the resulting combined
114 |  |
      * configuration (see below).</td>
115 |  |
      * </tr>
116 |  |
      * <tr>
117 |  |
      * <td valign="top"><code>config-at</code></td>
118 |  |
      * <td>With this attribute an optional prefix can be specified for the
119 |  |
      * properties of the corresponding configuration.</td>
120 |  |
      * </tr>
121 |  |
      * <tr>
122 |  |
      * <td valign="top"><code>config-optional</code></td>
123 |  |
      * <td>Declares a configuration as optional. This means that errors that occur
124 |  |
      * when creating the configuration are silently ignored.</td>
125 |  |
      * </tr>
126 |  |
      * </table>
127 |  |
      * </p>
128 |  |
      * <p>
129 |  |
      * The optional <em>header</em> section can contain some meta data about the
130 |  |
      * created configuration itself. For instance, it is possible to set further
131 |  |
      * properties of the <code>NodeCombiner</code> objects used for constructing
132 |  |
      * the resulting configuration.
133 |  |
      * </p>
134 |  |
      * <p>
135 |  |
      * The configuration object returned by this builder is an instance of the
136 |  |
      * <code>{@link CombinedConfiguration}</code> class. The return value of the
137 |  |
      * <code>getConfiguration()</code> method can be casted to this type, and the
138 |  |
      * <code>getConfiguration(boolean)</code> method directly declares
139 |  |
      * <code>CombinedConfiguration</code> as return type. This allows for
140 |  |
      * convenient access to the configuration objects maintained by the combined
141 |  |
      * configuration (e.g. for updates of single configuration objects). It has also
142 |  |
      * the advantage that the properties stored in all declared configuration
143 |  |
      * objects are collected and transformed into a single hierarchical structure,
144 |  |
      * which can be accessed using different expression engines.
145 |  |
      * </p>
146 |  |
      * <p>
147 |  |
      * All declared override configurations are directly added to the resulting
148 |  |
      * combined configuration. If they are given names (using the
149 |  |
      * <code>config-name</code> attribute), they can directly be accessed using
150 |  |
      * the <code>getConfiguration(String)</code> method of
151 |  |
      * <code>CombinedConfiguration</code>. The additional configurations are
152 |  |
      * alltogether added to another combined configuration, which uses a union
153 |  |
      * combiner. Then this union configuration is added to the resulting combined
154 |  |
      * configuration under the name defined by the <code>ADDITIONAL_NAME</code>
155 |  |
      * constant.
156 |  |
      * </p>
157 |  |
      * <p>
158 |  |
      * Implementation note: This class is not thread-safe. Especially the
159 |  |
      * <code>getConfiguration()</code> methods should be called by a single thread
160 |  |
      * only.
161 |  |
      * </p>
162 |  |
      *
163 |  |
      * @since 1.3
164 |  |
      * @author <a
165 |  |
      * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons
166 |  |
      * Configuration team</a>
167 |  |
      * @version $Id: DefaultConfigurationBuilder.java 384601 2006-03-09 20:22:58Z
168 |  |
      * oheger $
169 |  |
      */
170 | 18 |
     public class DefaultConfigurationBuilder extends XMLConfiguration implements
171 |  |
             ConfigurationBuilder
172 |  |
     {
173 |  |
         /**
174 |  |
          * Constant for the name of the additional configuration. If the
175 |  |
          * configuration definition file contains an <code>additional</code>
176 |  |
          * section, a special union configuration is created and added under this
177 |  |
          * name to the resulting combined configuration.
178 |  |
          */
179 | 4 |
         public static final String ADDITIONAL_NAME = DefaultConfigurationBuilder.class
180 |  |
                 .getName()
181 |  |
                 + "/ADDITIONAL_CONFIG";
182 |  |
183 |  |
         /** Constant for the expression engine used by this builder. */
184 | 2 |
         static final XPathExpressionEngine EXPRESSION_ENGINE = new XPathExpressionEngine();
185 |  |
186 |  |
         /** Constant for the name of the configuration bean factory. */
187 | 2 |
         static final String CONFIG_BEAN_FACTORY_NAME = DefaultConfigurationBuilder.class
188 |  |
                 .getName()
189 |  |
                 + ".CONFIG_BEAN_FACTORY_NAME";
190 |  |
191 |  |
         /** Constant for the reserved name attribute. */
192 |  |
         static final String ATTR_NAME = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
193 |  |
                 + XMLBeanDeclaration.RESERVED_PREFIX
194 |  |
                 + "name"
195 |  |
                 + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
196 |  |
197 |  |
         /** Constant for the name of the at attribute. */
198 |  |
         static final String ATTR_ATNAME = "at";
199 |  |
200 |  |
         /** Constant for the reserved at attribute. */
201 |  |
         static final String ATTR_AT_RES = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
202 |  |
                 + XMLBeanDeclaration.RESERVED_PREFIX
203 |  |
                 + ATTR_ATNAME
204 |  |
                 + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
205 |  |
206 |  |
         /** Constant for the at attribute without the reserved prefix. */
207 |  |
         static final String ATTR_AT = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
208 |  |
                 + ATTR_ATNAME + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
209 |  |
210 |  |
         /** Constant for the name of the optional attribute. */
211 |  |
         static final String ATTR_OPTIONALNAME = "optional";
212 |  |
213 |  |
         /** Constant for the reserved optional attribute. */
214 |  |
         static final String ATTR_OPTIONAL_RES = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
215 |  |
                 + XMLBeanDeclaration.RESERVED_PREFIX
216 |  |
                 + ATTR_OPTIONALNAME
217 |  |
                 + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
218 |  |
219 |  |
         /** Constant for the optional attribute without the reserved prefix. */
220 |  |
         static final String ATTR_OPTIONAL = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
221 |  |
                 + ATTR_OPTIONALNAME + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
222 |  |
223 |  |
         /** Constant for the file name attribute. */
224 |  |
         static final String ATTR_FILENAME = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
225 |  |
                 + "fileName" + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
226 |  |
227 |  |
         /** Constant for the name of the header section. */
228 |  |
         static final String SEC_HEADER = "header";
229 |  |
230 |  |
         /** Constant for an expression that selects the union configurations. */
231 |  |
         static final String KEY_UNION = "/additional/*";
232 |  |
233 |  |
         /** Constant for an expression that selects override configurations. */
234 |  |
         static final String KEY_OVERRIDE1 = "/*[local-name() != 'additional' and "
235 |  |
                 + "local-name() != 'override' and local-name() != '"
236 |  |
                 + SEC_HEADER + "']";
237 |  |
238 |  |
         /**
239 |  |
          * Constant for an expression that selects override configurations in the
240 |  |
          * override section.
241 |  |
          */
242 |  |
         static final String KEY_OVERRIDE2 = "/override/*";
243 |  |
244 |  |
         /**
245 |  |
          * Constant for the key that points to the list nodes definition of the
246 |  |
          * override combiner.
247 |  |
          */
248 |  |
         static final String KEY_OVERRIDE_LIST = SEC_HEADER
249 |  |
                 + "/combiner/override/list-nodes/node";
250 |  |
251 |  |
         /**
252 |  |
          * Constant for the key that points to the list nodes definition of the
253 |  |
          * additional combiner.
254 |  |
          */
255 |  |
         static final String KEY_ADDITIONAL_LIST = SEC_HEADER
256 |  |
                 + "/combiner/additional/list-nodes/node";
257 |  |
258 |  |
         /**
259 |  |
          * Constant for the key of the result declaration. This key can point to a
260 |  |
          * bean declaration, which defines properties of the resulting combined
261 |  |
          * configuration.
262 |  |
          */
263 |  |
         static final String KEY_RESULT = SEC_HEADER + "/result";
264 |  |
265 |  |
         /** Constant for the key of the combiner in the result declaration.*/
266 |  |
         static final String KEY_COMBINER = KEY_RESULT + "/nodeCombiner";
267 |  |
268 |  |
         /** Constant for the XML file extension. */
269 |  |
         static final String EXT_XML = ".xml";
270 |  |
271 |  |
         /** Constant for the provider for properties files. */
272 | 2 |
         private static final ConfigurationProvider PROPERTIES_PROVIDER = new FileExtensionConfigurationProvider(
273 |  |
                 XMLPropertiesConfiguration.class, PropertiesConfiguration.class,
274 |  |
                 EXT_XML);
275 |  |
276 |  |
         /** Constant for the provider for XML files. */
277 | 2 |
         private static final ConfigurationProvider XML_PROVIDER = new FileConfigurationProvider(
278 |  |
                 XMLConfiguration.class);
279 |  |
280 |  |
         /** Constant for the provider for JNDI sources. */
281 | 2 |
         private static final ConfigurationProvider JNDI_PROVIDER = new ConfigurationProvider(
282 |  |
                 JNDIConfiguration.class);
283 |  |
284 |  |
         /** Constant for the provider for system properties. */
285 | 2 |
         private static final ConfigurationProvider SYSTEM_PROVIDER = new ConfigurationProvider(
286 |  |
                 SystemConfiguration.class);
287 |  |
288 |  |
         /** Constant for the provider for plist files. */
289 | 2 |
         private static final ConfigurationProvider PLIST_PROVIDER = new FileExtensionConfigurationProvider(
290 |  |
                 XMLPropertyListConfiguration.class,
291 |  |
                 PropertyListConfiguration.class, EXT_XML);
292 |  |
293 |  |
         /** Constant for the provider for configuration definition files.*/
294 | 2 |
         private static final ConfigurationProvider BUILDER_PROVIDER = new ConfigurationBuilderProvider();
295 |  |
296 |  |
         /** An array with the names of the default tags. */
297 | 2 |
         private static final String[] DEFAULT_TAGS =
298 |  |
         {"properties", "xml", "hierarchicalXml", "jndi", "system", "plist", "configuration"};
299 |  |
300 |  |
         /** An array with the providers for the default tags. */
301 | 2 |
         private static final ConfigurationProvider[] DEFAULT_PROVIDERS =
302 |  |
         {PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER, JNDI_PROVIDER,
303 |  |
                 SYSTEM_PROVIDER, PLIST_PROVIDER, BUILDER_PROVIDER};
304 |  |
305 |  |
         /**
306 |  |
          * The serial version UID.
307 |  |
          */
308 |  |
         private static final long serialVersionUID = -3113777854714492123L;
309 |  |
310 |  |
         /** Stores the configuration that is currently constructed.*/
311 |  |
         private CombinedConfiguration constructedConfiguration;
312 |  |
313 |  |
         /** Stores a map with the registered configuration providers. */
314 |  |
         private Map providers;
315 |  |
316 |  |
         /** Stores the base path to the configuration sources to load. */
317 |  |
         private String configurationBasePath;
318 |  |
319 |  |
         /**
320 |  |
          * Creates a new instance of <code>DefaultConfigurationBuilder</code>. A
321 |  |
          * configuration definition file is not yet loaded. Use the diverse setter
322 |  |
          * methods provided by file based configurations to specify the
323 |  |
          * configuration definition file.
324 |  |
          */
325 |  |
         public DefaultConfigurationBuilder()
326 |  |
         {
327 | 31 |
             super();
328 | 31 |
             providers = new HashMap();
329 | 31 |
             setExpressionEngine(EXPRESSION_ENGINE);
330 | 31 |
             registerDefaultProviders();
331 | 31 |
         }
332 |  |
333 |  |
         /**
334 |  |
          * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
335 |  |
          * sets the specified configuration definition file.
336 |  |
          *
337 |  |
          * @param file the configuration definition file
338 |  |
          */
339 |  |
         public DefaultConfigurationBuilder(File file)
340 |  |
         {
341 | 1 |
             this();
342 | 1 |
             setFile(file);
343 | 1 |
         }
344 |  |
345 |  |
         /**
346 |  |
          * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
347 |  |
          * sets the specified configuration definition file.
348 |  |
          *
349 |  |
          * @param fileName the name of the configuration definition file
350 |  |
          * @throws ConfigurationException if an error occurs when the file is loaded
351 |  |
          */
352 |  |
         public DefaultConfigurationBuilder(String fileName)
353 |  |
                 throws ConfigurationException
354 |  |
         {
355 | 2 |
             this();
356 | 2 |
             setFileName(fileName);
357 | 2 |
         }
358 |  |
359 |  |
         /**
360 |  |
          * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
361 |  |
          * sets the specified configuration definition file.
362 |  |
          *
363 |  |
          * @param url the URL to the configuration definition file
364 |  |
          * @throws ConfigurationException if an error occurs when the file is loaded
365 |  |
          */
366 |  |
         public DefaultConfigurationBuilder(URL url) throws ConfigurationException
367 |  |
         {
368 | 1 |
             this();
369 | 1 |
             setURL(url);
370 | 1 |
         }
371 |  |
372 |  |
         /**
373 |  |
          * Returns the base path for the configuration sources to load. This path is
374 |  |
          * used to resolve relative paths in the configuration definition file.
375 |  |
          *
376 |  |
          * @return the base path for configuration sources
377 |  |
          */
378 |  |
         public String getConfigurationBasePath()
379 |  |
         {
380 | 50 |
             return (configurationBasePath != null) ? configurationBasePath
381 |  |
                     : getBasePath();
382 |  |
         }
383 |  |
384 |  |
         /**
385 |  |
          * Sets the base path for the configuration sources to load. Normally a base
386 |  |
          * path need not to be set because it is determined by the location of the
387 |  |
          * configuration definition file to load. All relative pathes in this file
388 |  |
          * are resolved relative to this file. Setting a base path makes sense if
389 |  |
          * such relative pathes should be otherwise resolved, e.g. if the
390 |  |
          * configuration file is loaded from the class path and all sub
391 |  |
          * configurations it refers to are stored in a special config directory.
392 |  |
          *
393 |  |
          * @param configurationBasePath the new base path to set
394 |  |
          */
395 |  |
         public void setConfigurationBasePath(String configurationBasePath)
396 |  |
         {
397 | 1 |
             this.configurationBasePath = configurationBasePath;
398 | 1 |
         }
399 |  |
400 |  |
         /**
401 |  |
          * Adds a configuration provider for the specified tag. Whenever this tag is
402 |  |
          * encountered in the configuration definition file this provider will be
403 |  |
          * called to create the configuration object.
404 |  |
          *
405 |  |
          * @param tagName the name of the tag in the configuration definition file
406 |  |
          * @param provider the provider for this tag
407 |  |
          */
408 |  |
         public void addConfigurationProvider(String tagName,
409 |  |
                 ConfigurationProvider provider)
410 |  |
         {
411 | 222 |
             if (tagName == null)
412 |  |
             {
413 | 1 |
                 throw new IllegalArgumentException("Tag name must not be null!");
414 |  |
             }
415 | 221 |
             if (provider == null)
416 |  |
             {
417 | 1 |
                 throw new IllegalArgumentException("Provider must not be null!");
418 |  |
             }
419 |  |
420 | 220 |
             providers.put(tagName, provider);
421 | 220 |
         }
422 |  |
423 |  |
         /**
424 |  |
          * Removes the configuration provider for the specified tag name.
425 |  |
          *
426 |  |
          * @param tagName the tag name
427 |  |
          * @return the removed configuration provider or <b>null</b> if none was
428 |  |
          * registered for that tag
429 |  |
          */
430 |  |
         public ConfigurationProvider removeConfigurationProvider(String tagName)
431 |  |
         {
432 | 3 |
             return (ConfigurationProvider) providers.remove(tagName);
433 |  |
         }
434 |  |
435 |  |
         /**
436 |  |
          * Returns the configuration provider for the given tag.
437 |  |
          *
438 |  |
          * @param tagName the name of the tag
439 |  |
          * @return the provider that was registered for this tag or <b>null</b> if
440 |  |
          * there is none
441 |  |
          */
442 |  |
         public ConfigurationProvider providerForTag(String tagName)
443 |  |
         {
444 | 62 |
             return (ConfigurationProvider) providers.get(tagName);
445 |  |
         }
446 |  |
447 |  |
         /**
448 |  |
          * Returns the configuration provided by this builder. Loads and parses the
449 |  |
          * configuration definition file and creates instances for the declared
450 |  |
          * configurations.
451 |  |
          *
452 |  |
          * @return the configuration
453 |  |
          * @throws ConfigurationException if an error occurs
454 |  |
          */
455 |  |
         public Configuration getConfiguration() throws ConfigurationException
456 |  |
         {
457 | 10 |
             return getConfiguration(true);
458 |  |
         }
459 |  |
460 |  |
         /**
461 |  |
          * Returns the configuration provided by this builder. If the boolean
462 |  |
          * parameter is <b>true</b>, the configuration definition file will be
463 |  |
          * loaded. It will then be parsed, and instances for the declared
464 |  |
          * configurations will be created.
465 |  |
          *
466 |  |
          * @param load a flag whether the configuration definition file should be
467 |  |
          * loaded; a value of <b>false</b> would make sense if the file has already
468 |  |
          * been created or its content was manipulated using some of the property
469 |  |
          * accessor methods
470 |  |
          * @return the configuration
471 |  |
          * @throws ConfigurationException if an error occurs
472 |  |
          */
473 |  |
         public CombinedConfiguration getConfiguration(boolean load)
474 |  |
                 throws ConfigurationException
475 |  |
         {
476 | 18 |
             if (load)
477 |  |
             {
478 | 15 |
                 load();
479 |  |
             }
480 |  |
481 | 17 |
             CombinedConfiguration result = createResultConfiguration();
482 | 17 |
             constructedConfiguration = result;
483 |  |
484 | 17 |
             List overrides = configurationsAt(KEY_OVERRIDE1);
485 | 17 |
             overrides.addAll(configurationsAt(KEY_OVERRIDE2));
486 | 17 |
             initCombinedConfiguration(result, overrides, KEY_OVERRIDE_LIST);
487 |  |
488 | 16 |
             List additionals = configurationsAt(KEY_UNION);
489 | 16 |
             if (!additionals.isEmpty())
490 |  |
             {
491 | 6 |
                 CombinedConfiguration addConfig = new CombinedConfiguration(
492 |  |
                         new UnionCombiner());
493 | 6 |
                 result.addConfiguration(addConfig, ADDITIONAL_NAME);
494 | 6 |
                 initCombinedConfiguration(addConfig, additionals,
495 |  |
                         KEY_ADDITIONAL_LIST);
496 |  |
             }
497 |  |
498 | 16 |
             return result;
499 |  |
         }
500 |  |
501 |  |
         /**
502 |  |
          * Creates the resulting combined configuration. This method is called by
503 |  |
          * <code>getConfiguration()</code>. It checks whether the
504 |  |
          * <code>header</code> section of the configuration definition file
505 |  |
          * contains a <code>result</code> element. If this is the case, it will be
506 |  |
          * used to initialize the properties of the newly created configuration
507 |  |
          * object.
508 |  |
          *
509 |  |
          * @return the resulting configuration object
510 |  |
          * @throws ConfigurationException if an error occurs
511 |  |
          */
512 |  |
         protected CombinedConfiguration createResultConfiguration()
513 |  |
                 throws ConfigurationException
514 |  |
         {
515 | 17 |
             XMLBeanDeclaration decl = new XMLBeanDeclaration(this, KEY_RESULT, true);
516 | 17 |
             CombinedConfiguration result = (CombinedConfiguration) BeanHelper
517 |  |
                     .createBean(decl, CombinedConfiguration.class);
518 |  |
519 | 17 |
             if (getMaxIndex(KEY_COMBINER) < 0)
520 |  |
             {
521 |  |
                 // No combiner defined => set default
522 | 14 |
                 result.setNodeCombiner(new OverrideCombiner());
523 |  |
             }
524 |  |
525 | 17 |
             return result;
526 |  |
         }
527 |  |
528 |  |
         /**
529 |  |
          * Initializes a combined configuration for the configurations of a specific
530 |  |
          * section. This method is called for the override and for the additional
531 |  |
          * section (if it exists).
532 |  |
          *
533 |  |
          * @param config the configuration to be initialized
534 |  |
          * @param containedConfigs the list with the declaratinos of the contained
535 |  |
          * configurations
536 |  |
          * @param keyListNodes a list with the declaration of list nodes
537 |  |
          * @throws ConfigurationException if an error occurs
538 |  |
          */
539 |  |
         protected void initCombinedConfiguration(CombinedConfiguration config,
540 |  |
                 List containedConfigs, String keyListNodes) throws ConfigurationException
541 |  |
         {
542 | 23 |
             List listNodes = getList(keyListNodes);
543 | 52 |
             for (Iterator it = listNodes.iterator(); it.hasNext();)
544 |  |
             {
545 | 6 |
                 config.getNodeCombiner().addListNode((String) it.next());
546 |  |
             }
547 |  |
548 | 102 |
             for (Iterator it = containedConfigs.iterator(); it.hasNext();)
549 |  |
             {
550 | 57 |
                 HierarchicalConfiguration conf = (HierarchicalConfiguration) it
551 |  |
                         .next();
552 | 57 |
                 ConfigurationDeclaration decl = new ConfigurationDeclaration(this,
553 |  |
                         conf);
554 | 57 |
                 AbstractConfiguration newConf = createConfigurationAt(decl);
555 | 56 |
                 if (newConf != null)
556 |  |
                 {
557 | 48 |
                     config.addConfiguration(newConf, decl.getConfiguration()
558 |  |
                             .getString(ATTR_NAME), decl.getAt());
559 |  |
                 }
560 |  |
             }
561 | 22 |
         }
562 |  |
563 |  |
         /**
564 |  |
          * Registers the default configuration providers supported by this class.
565 |  |
          * This method will be called during initialization. It registers
566 |  |
          * configuration providers for the tags that are supported by default.
567 |  |
          */
568 |  |
         protected void registerDefaultProviders()
569 |  |
         {
570 | 248 |
             for (int i = 0; i < DEFAULT_TAGS.length; i++)
571 |  |
             {
572 | 217 |
                 addConfigurationProvider(DEFAULT_TAGS[i], DEFAULT_PROVIDERS[i]);
573 |  |
             }
574 | 31 |
         }
575 |  |
576 |  |
         /**
577 |  |
          * Performs interpolation. This method will not only take this configuration
578 |  |
          * instance into account (which is the one that loaded the configuration
579 |  |
          * definition file), but also the so far constructed combined configuration.
580 |  |
          * So variables can be used that point to properties that are defined in
581 |  |
          * configuration sources loaded by this builder.
582 |  |
          *
583 |  |
          * @param value the value to be interpolated
584 |  |
          * @return the interpolated value
585 |  |
          */
586 |  |
         protected Object interpolate(Object value)
587 |  |
         {
588 | 309 |
             Object result = super.interpolate(value);
589 | 309 |
             if (constructedConfiguration != null)
590 |  |
             {
591 | 252 |
                 result = constructedConfiguration.interpolate(result);
592 |  |
             }
593 | 309 |
             return result;
594 |  |
         }
595 |  |
596 |  |
         /**
597 |  |
          * Creates a configuration object from the specified configuration
598 |  |
          * declaration.
599 |  |
          *
600 |  |
          * @param decl the configuration declaration
601 |  |
          * @return the new configuration object
602 |  |
          * @throws ConfigurationException if an error occurs
603 |  |
          */
604 |  |
         private AbstractConfiguration createConfigurationAt(
605 |  |
                 ConfigurationDeclaration decl) throws ConfigurationException
606 |  |
         {
607 |  |
             try
608 |  |
             {
609 | 57 |
                 return (AbstractConfiguration) BeanHelper.createBean(decl);
610 |  |
             }
611 |  |
             catch (Exception ex)
612 |  |
             {
613 |  |
                 // redirect to configuration exceptions
614 | 1 |
                 throw new ConfigurationException(ex);
615 |  |
             }
616 |  |
         }
617 |  |
618 |  |
         /**
619 |  |
          * <p>
620 |  |
          * A base class for creating and initializing configuration sources.
621 |  |
          * </p>
622 |  |
          * <p>
623 |  |
          * Concrete sub classes of this base class are responsible for creating
624 |  |
          * specific <code>Configuration</code> objects for the tags in the
625 |  |
          * configuration definition file. The configuration factory will parse the
626 |  |
          * definition file and try to find a matching
627 |  |
          * <code>ConfigurationProvider</code> for each encountered tag. This
628 |  |
          * provider is then asked to create a corresponding
629 |  |
          * <code>Configuration</code> object. It is up to a concrete
630 |  |
          * implementation how this object is created and initialized.
631 |  |
          * </p>
632 |  |
          * <p>
633 |  |
          * Note that at the moment only configuration classes derived from
634 |  |
          * <code>{@link AbstractConfiguration}</code> are supported.
635 |  |
          * </p>
636 |  |
          */
637 |  |
         public static class ConfigurationProvider extends DefaultBeanFactory
638 |  |
         {
639 |  |
             /** Stores the class of the configuration to be created. */
640 |  |
             private Class configurationClass;
641 |  |
642 |  |
             /**
643 |  |
              * Creates a new uninitialized instance of
644 |  |
              * <code>ConfigurationProvider</code>.
645 |  |
              */
646 |  |
             public ConfigurationProvider()
647 |  |
             {
648 | 7 |
                 this(null);
649 | 7 |
             }
650 |  |
651 |  |
             /**
652 |  |
              * Creates a new instance of <code>ConfigurationProvider</code> and
653 |  |
              * sets the class of the configuration created by this provider.
654 |  |
              *
655 |  |
              * @param configClass the configuration class
656 |  |
              */
657 |  |
             public ConfigurationProvider(Class configClass)
658 | 16 |
             {
659 | 16 |
                 setConfigurationClass(configClass);
660 | 16 |
             }
661 |  |
662 |  |
             /**
663 |  |
              * Returns the class of the configuration returned by this provider.
664 |  |
              *
665 |  |
              * @return the class of the provided configuration
666 |  |
              */
667 |  |
             public Class getConfigurationClass()
668 |  |
             {
669 | 58 |
                 return configurationClass;
670 |  |
             }
671 |  |
672 |  |
             /**
673 |  |
              * Sets the class of the configuration returned by this provider.
674 |  |
              *
675 |  |
              * @param configurationClass the configuration class
676 |  |
              */
677 |  |
             public void setConfigurationClass(Class configurationClass)
678 |  |
             {
679 | 16 |
                 this.configurationClass = configurationClass;
680 | 16 |
             }
681 |  |
682 |  |
             /**
683 |  |
              * Returns the configuration. This method is called to fetch the
684 |  |
              * configuration from the provider. This implementation will call the
685 |  |
              * inherited
686 |  |
              * <code>{@link org.apache.commons.configuration.beanutils.DefaultBeanFactory#createBean(Class, BeanDeclaration, Object) createBean()}</code>
687 |  |
              * method to create a new instance of the configuration class.
688 |  |
              *
689 |  |
              * @param decl the bean declaration with initialization parameters for
690 |  |
              * the configuration
691 |  |
              * @return the new configuration object
692 |  |
              * @throws Exception if an error occurs
693 |  |
              */
694 |  |
             public AbstractConfiguration getConfiguration(
695 |  |
                     ConfigurationDeclaration decl) throws Exception
696 |  |
             {
697 | 58 |
                 return (AbstractConfiguration) createBean(getConfigurationClass(),
698 |  |
                         decl, null);
699 |  |
             }
700 |  |
         }
701 |  |
702 |  |
         /**
703 |  |
          * <p>
704 |  |
          * A specialized <code>BeanDeclaration</code> implementation that
705 |  |
          * represents the declaration of a configuration source.
706 |  |
          * </p>
707 |  |
          * <p>
708 |  |
          * Instances of this class are able to extract all information about a
709 |  |
          * configuration source from the configuration definition file. The
710 |  |
          * declaration of a configuration source is very similar to a bean
711 |  |
          * declaration processed by <code>XMLBeanDeclaration</code>. There are
712 |  |
          * very few differences, e.g. the two reserved attributes
713 |  |
          * <code>optional</code> and <code>at</code> and the fact that a bean
714 |  |
          * factory is never needed.
715 |  |
          * </p>
716 |  |
          */
717 | 2 |
         protected static class ConfigurationDeclaration extends XMLBeanDeclaration
718 |  |
         {
719 |  |
             /** Stores a reference to the associated configuration builder. */
720 |  |
             private DefaultConfigurationBuilder configurationBuilder;
721 |  |
722 |  |
             /**
723 |  |
              * Creates a new instance of <code>ConfigurationDeclaration</code> and
724 |  |
              * initializes it.
725 |  |
              *
726 |  |
              * @param builder the associated configuration builder
727 |  |
              * @param config the configuration this declaration is based onto
728 |  |
              */
729 |  |
             public ConfigurationDeclaration(DefaultConfigurationBuilder builder,
730 |  |
                     HierarchicalConfiguration config)
731 |  |
             {
732 | 63 |
                 super(config);
733 | 63 |
                 configurationBuilder = builder;
734 | 63 |
             }
735 |  |
736 |  |
             /**
737 |  |
              * Returns the associated configuration builder.
738 |  |
              *
739 |  |
              * @return the configuration builder
740 |  |
              */
741 |  |
             public DefaultConfigurationBuilder getConfigurationBuilder()
742 |  |
             {
743 | 166 |
                 return configurationBuilder;
744 |  |
             }
745 |  |
746 |  |
             /**
747 |  |
              * Returns the value of the <code>at</code> attribute.
748 |  |
              *
749 |  |
              * @return the value of the <code>at</code> attribute (can be <b>null</b>)
750 |  |
              */
751 |  |
             public String getAt()
752 |  |
             {
753 | 52 |
                 String result = this.getConfiguration().getString(ATTR_AT_RES);
754 | 52 |
                 return (result == null) ? this.getConfiguration().getString(ATTR_AT)
755 |  |
                         : result;
756 |  |
             }
757 |  |
758 |  |
             /**
759 |  |
              * Returns a flag whether this is an optional configuration.
760 |  |
              *
761 |  |
              * @return a flag if this declaration points to an optional
762 |  |
              * configuration
763 |  |
              */
764 |  |
             public boolean isOptional()
765 |  |
             {
766 | 14 |
                 Boolean value = this.getConfiguration().getBoolean(ATTR_OPTIONAL_RES,
767 |  |
                         null);
768 | 14 |
                 if (value == null)
769 |  |
                 {
770 | 11 |
                     value = this.getConfiguration().getBoolean(ATTR_OPTIONAL,
771 |  |
                             Boolean.FALSE);
772 |  |
                 }
773 | 13 |
                 return value.booleanValue();
774 |  |
             }
775 |  |
776 |  |
             /**
777 |  |
              * Returns the name of the bean factory. For configuration source
778 |  |
              * declarations always a reserved factory is used. This factory's name
779 |  |
              * is returned by this implementation.
780 |  |
              *
781 |  |
              * @return the name of the bean factory
782 |  |
              */
783 |  |
             public String getBeanFactoryName()
784 |  |
             {
785 | 59 |
                 return CONFIG_BEAN_FACTORY_NAME;
786 |  |
             }
787 |  |
788 |  |
             /**
789 |  |
              * Returns the bean's class name. This implementation will always return
790 |  |
              * <b>null</b>.
791 |  |
              *
792 |  |
              * @return the name of the bean's class
793 |  |
              */
794 |  |
             public String getBeanClassName()
795 |  |
             {
796 | 59 |
                 return null;
797 |  |
             }
798 |  |
799 |  |
             /**
800 |  |
              * Checks whether the given node is reserved. This method will take
801 |  |
              * further reserved attributes into account
802 |  |
              *
803 |  |
              * @param nd the node
804 |  |
              * @return a flag whether this node is reserved
805 |  |
              */
806 |  |
             protected boolean isReservedNode(ConfigurationNode nd)
807 |  |
             {
808 | 102 |
                 if (super.isReservedNode(nd))
809 |  |
                 {
810 | 21 |
                     return true;
811 |  |
                 }
812 |  |
813 | 81 |
                 return nd.isAttribute()
814 |  |
                         && ((ATTR_ATNAME.equals(nd.getName()) && nd.getParentNode()
815 |  |
                                 .getAttributeCount(RESERVED_PREFIX + ATTR_ATNAME) == 0) || (ATTR_OPTIONALNAME
816 |  |
                                 .equals(nd.getName()) && nd.getParentNode()
817 |  |
                                 .getAttributeCount(RESERVED_PREFIX + ATTR_OPTIONALNAME) == 0));
818 |  |
             }
819 |  |
820 |  |
             /**
821 |  |
              * Performs interpolation. This implementation will delegate
822 |  |
              * interpolation to the configuration builder, which takes care that the
823 |  |
              * currently constructed configuration is taken into account, too.
824 |  |
              *
825 |  |
              * @param value the value to be interpolated
826 |  |
              * @return the interpolated value
827 |  |
              */
828 |  |
             protected Object interpolate(Object value)
829 |  |
             {
830 | 57 |
                 return getConfigurationBuilder().interpolate(value);
831 |  |
             }
832 |  |
         }
833 |  |
834 |  |
         /**
835 |  |
          * A specialized <code>BeanFactory</code> implementation that handles
836 |  |
          * configuration declarations. This class will retrieve the correct
837 |  |
          * configuration provider and delegate the task of creating the
838 |  |
          * configuration to this object.
839 |  |
          */
840 | 2 |
         static class ConfigurationBeanFactory implements BeanFactory
841 |  |
         {
842 |  |
             /**
843 |  |
              * Creates an instance of a bean class. This implementation expects that
844 |  |
              * the passed in bean declaration is a declaration for a configuration.
845 |  |
              * It will determine the responsible configuration provider and delegate
846 |  |
              * the call to this instance. If creation of the configuration fails
847 |  |
              * and the <code>optional</code> attribute is set, the exception will
848 |  |
              * be ignored and <b>null</b> will be returned.
849 |  |
              *
850 |  |
              * @param beanClass the bean class (will be ignored)
851 |  |
              * @param data the declaration
852 |  |
              * @param param an additional parameter (will be ignored)
853 |  |
              * @return the newly created configuration
854 |  |
              * @throws Exception if an error occurs
855 |  |
              */
856 |  |
             public Object createBean(Class beanClass, BeanDeclaration data,
857 |  |
                     Object param) throws Exception
858 |  |
             {
859 | 59 |
                 ConfigurationDeclaration decl = (ConfigurationDeclaration) data;
860 | 59 |
                 String tagName = decl.getNode().getName();
861 | 59 |
                 ConfigurationProvider provider = decl.getConfigurationBuilder()
862 |  |
                         .providerForTag(tagName);
863 | 59 |
                 if (provider == null)
864 |  |
                 {
865 | 1 |
                     throw new ConfigurationRuntimeException(
866 |  |
                             "No ConfigurationProvider registered for tag "
867 |  |
                                     + tagName);
868 |  |
                 }
869 |  |
870 |  |
                 try
871 |  |
                 {
872 | 58 |
                     return provider.getConfiguration(decl);
873 |  |
                 }
874 |  |
                 catch (Exception ex)
875 |  |
                 {
876 |  |
                     // If this is an optional configuration, ignore the exception
877 | 9 |
                     if (!decl.isOptional())
878 |  |
                     {
879 | 1 |
                         throw ex;
880 |  |
                     }
881 |  |
                     else
882 |  |
                     {
883 | 8 |
                         return null;
884 |  |
                     }
885 |  |
                 }
886 |  |
             }
887 |  |
888 |  |
             /**
889 |  |
              * Returns the default class for this bean factory.
890 |  |
              *
891 |  |
              * @return the default class
892 |  |
              */
893 |  |
             public Class getDefaultBeanClass()
894 |  |
             {
895 |  |
                 // Here some valid class must be returned, otherwise BeanHelper
896 |  |
                 // will complain that the bean's class cannot be determined
897 | 59 |
                 return Configuration.class;
898 |  |
             }
899 |  |
         }
900 |  |
901 |  |
         /**
902 |  |
          * A specialized provider implementation that deals with file based
903 |  |
          * configurations. Ensures that the base path is correctly set and that the
904 |  |
          * load() method gets called.
905 |  |
          */
906 |  |
         public static class FileConfigurationProvider extends ConfigurationProvider
907 |  |
         {
908 |  |
             /**
909 |  |
              * Creates a new instance of <code>FileConfigurationProvider</code>.
910 |  |
              */
911 |  |
             public FileConfigurationProvider()
912 |  |
             {
913 | 4 |
                 super();
914 | 4 |
             }
915 |  |
916 |  |
             /**
917 |  |
              * Creates a new instance of <code>FileConfigurationProvider</code>
918 |  |
              * and sets the configuration class.
919 |  |
              *
920 |  |
              * @param configClass the class for the configurations to be created
921 |  |
              */
922 |  |
             public FileConfigurationProvider(Class configClass)
923 |  |
             {
924 | 2 |
                 super(configClass);
925 | 2 |
             }
926 |  |
927 |  |
             /**
928 |  |
              * Creates the configuration. After that <code>load()</code> will be
929 |  |
              * called. If this configuration is marked as optional, exceptions will
930 |  |
              * be ignored.
931 |  |
              *
932 |  |
              * @param decl the declaration
933 |  |
              * @return the new configuration
934 |  |
              * @throws Exception if an error occurs
935 |  |
              */
936 |  |
             public AbstractConfiguration getConfiguration(
937 |  |
                     ConfigurationDeclaration decl) throws Exception
938 |  |
             {
939 | 50 |
                 FileConfiguration config = (FileConfiguration) super
940 |  |
                         .getConfiguration(decl);
941 | 50 |
                 config.load();
942 | 42 |
                 return (AbstractConfiguration) config;
943 |  |
             }
944 |  |
945 |  |
             /**
946 |  |
              * Initializes the bean instance. Ensures that the file configuration's
947 |  |
              * base path will be initialized with the base path of the factory so
948 |  |
              * that relative path names can be correctly resolved.
949 |  |
              *
950 |  |
              * @param bean the bean to be initialized
951 |  |
              * @param data the declaration
952 |  |
              * @throws Exception if an error occurs
953 |  |
              */
954 |  |
             protected void initBeanInstance(Object bean, BeanDeclaration data)
955 |  |
                     throws Exception
956 |  |
             {
957 | 50 |
                 FileConfiguration config = (FileConfiguration) bean;
958 | 50 |
                 config.setBasePath(((ConfigurationDeclaration) data)
959 |  |
                         .getConfigurationBuilder().getConfigurationBasePath());
960 | 50 |
                 super.initBeanInstance(bean, data);
961 | 50 |
             }
962 |  |
         }
963 |  |
964 |  |
         /**
965 |  |
          * A specialized configuration provider for file based configurations that
966 |  |
          * can handle configuration sources whose concrete type depends on the
967 |  |
          * extension of the file to be loaded. One example is the
968 |  |
          * <code>properties</code> tag: if the file ends with ".xml" a
969 |  |
          * XMLPropertiesConfiguration object must be created, otherwise a
970 |  |
          * PropertiesConfiguration object.
971 |  |
          */
972 | 2 |
         static class FileExtensionConfigurationProvider extends
973 |  |
                 FileConfigurationProvider
974 |  |
         {
975 |  |
             /** Stores the class to be created when the file extension matches. */
976 |  |
             private Class matchingClass;
977 |  |
978 |  |
             /**
979 |  |
              * Stores the class to be created when the file extension does not
980 |  |
              * match.
981 |  |
              */
982 |  |
             private Class defaultClass;
983 |  |
984 |  |
             /** Stores the file extension to be checked against. */
985 |  |
             private String fileExtension;
986 |  |
987 |  |
             /**
988 |  |
              * Creates a new instance of
989 |  |
              * <code>FileExtensionConfigurationProvider</code> and initializes it.
990 |  |
              *
991 |  |
              * @param matchingClass the class to be created when the file extension
992 |  |
              * matches
993 |  |
              * @param defaultClass the class to be created when the file extension
994 |  |
              * does not match
995 |  |
              * @param extension the file extension to be checked agains
996 |  |
              */
997 |  |
             public FileExtensionConfigurationProvider(Class matchingClass,
998 |  |
                     Class defaultClass, String extension)
999 | 4 |
             {
1000 | 4 |
                 this.matchingClass = matchingClass;
1001 | 4 |
                 this.defaultClass = defaultClass;
1002 | 4 |
                 fileExtension = extension;
1003 | 4 |
             }
1004 |  |
1005 |  |
             /**
1006 |  |
              * Creates the configuration object. The class is determined by the file
1007 |  |
              * name's extension.
1008 |  |
              *
1009 |  |
              * @param beanClass the class
1010 |  |
              * @param data the bean declaration
1011 |  |
              * @return the new bean
1012 |  |
              * @throws Exception if an error occurs
1013 |  |
              */
1014 |  |
             protected Object createBeanInstance(Class beanClass,
1015 |  |
                     BeanDeclaration data) throws Exception
1016 |  |
             {
1017 | 26 |
                 String fileName = ((ConfigurationDeclaration) data)
1018 |  |
                         .getConfiguration().getString(ATTR_FILENAME);
1019 | 26 |
                 if (fileName != null
1020 |  |
                         && fileName.toLowerCase().trim().endsWith(fileExtension))
1021 |  |
                 {
1022 | 6 |
                     return super.createBeanInstance(matchingClass, data);
1023 |  |
                 }
1024 |  |
                 else
1025 |  |
                 {
1026 | 20 |
                     return super.createBeanInstance(defaultClass, data);
1027 |  |
                 }
1028 |  |
             }
1029 |  |
         }
1030 |  |
1031 |  |
         /**
1032 |  |
          * A specialized configuration provider class that allows to include other
1033 |  |
          * configuration definition files.
1034 |  |
          */
1035 |  |
         static class ConfigurationBuilderProvider extends ConfigurationProvider
1036 |  |
         {
1037 |  |
             /**
1038 |  |
              * Creates a new instance of <code>ConfigurationBuilderProvider</code>.
1039 |  |
              */
1040 |  |
             public ConfigurationBuilderProvider()
1041 |  |
             {
1042 | 2 |
                 super(DefaultConfigurationBuilder.class);
1043 | 2 |
             }
1044 |  |
1045 |  |
             /**
1046 |  |
              * Creates the configuration. First creates a configuration builder
1047 |  |
              * object. Then returns the configuration created by this builder.
1048 |  |
              *
1049 |  |
              * @param decl the configuration declaration
1050 |  |
              * @return the configuration
1051 |  |
              * @exception Exception if an error occurs
1052 |  |
              */
1053 |  |
             public AbstractConfiguration getConfiguration(
1054 |  |
                     ConfigurationDeclaration decl) throws Exception
1055 |  |
             {
1056 | 2 |
                 DefaultConfigurationBuilder builder = (DefaultConfigurationBuilder) super
1057 |  |
                         .getConfiguration(decl);
1058 | 2 |
                 return builder.getConfiguration(true);
1059 |  |
             }
1060 |  |
         }
1061 |  |
1062 |  |
         static
1063 |  |
         {
1064 |  |
             // register the configuration bean factory
1065 | 2 |
             BeanHelper.registerBeanFactory(CONFIG_BEAN_FACTORY_NAME,
1066 |  |
                     new ConfigurationBeanFactory());
1067 |  |
         }
1068 |  |
     }