View Javadoc

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.ArrayList;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.commons.configuration.beanutils.BeanDeclaration;
29  import org.apache.commons.configuration.beanutils.BeanFactory;
30  import org.apache.commons.configuration.beanutils.BeanHelper;
31  import org.apache.commons.configuration.beanutils.DefaultBeanFactory;
32  import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;
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.logging.LogFactory;
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   * predefined 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 ignored. (However
125  * <code>{@link org.apache.commons.configuration.event.ConfigurationErrorListener}</code>s
126  * registered at the builder instance will get notified about this error: they
127  * receive an event of type <code>EVENT_ERR_LOAD_OPTIONAL</code>. The key
128  * property of this event contains the name of the optional configuration source
129  * that caused this problem.)</td>
130  * </tr>
131  * </table>
132  * </p>
133  * <p>
134  * The optional <em>header</em> section can contain some meta data about the
135  * created configuration itself. For instance, it is possible to set further
136  * properties of the <code>NodeCombiner</code> objects used for constructing
137  * the resulting configuration.
138  * </p>
139  * <p>
140  * The configuration object returned by this builder is an instance of the
141  * <code>{@link CombinedConfiguration}</code> class. The return value of the
142  * <code>getConfiguration()</code> method can be casted to this type, and the
143  * <code>getConfiguration(boolean)</code> method directly declares
144  * <code>CombinedConfiguration</code> as return type. This allows for
145  * convenient access to the configuration objects maintained by the combined
146  * configuration (e.g. for updates of single configuration objects). It has also
147  * the advantage that the properties stored in all declared configuration
148  * objects are collected and transformed into a single hierarchical structure,
149  * which can be accessed using different expression engines.
150  * </p>
151  * <p>
152  * All declared override configurations are directly added to the resulting
153  * combined configuration. If they are given names (using the
154  * <code>config-name</code> attribute), they can directly be accessed using
155  * the <code>getConfiguration(String)</code> method of
156  * <code>CombinedConfiguration</code>. The additional configurations are
157  * alltogether added to another combined configuration, which uses a union
158  * combiner. Then this union configuration is added to the resulting combined
159  * configuration under the name defined by the <code>ADDITIONAL_NAME</code>
160  * constant.
161  * </p>
162  * <p>
163  * Implementation note: This class is not thread-safe. Especially the
164  * <code>getConfiguration()</code> methods should be called by a single thread
165  * only.
166  * </p>
167  *
168  * @since 1.3
169  * @author <a
170  * href="http://commons.apache.org/configuration/team-list.html">Commons
171  * Configuration team</a>
172  * @version $Id: DefaultConfigurationBuilder.java 595043 2007-11-14 20:44:43Z oheger $
173  */
174 public class DefaultConfigurationBuilder extends XMLConfiguration implements
175         ConfigurationBuilder
176 {
177     /***
178      * Constant for the name of the additional configuration. If the
179      * configuration definition file contains an <code>additional</code>
180      * section, a special union configuration is created and added under this
181      * name to the resulting combined configuration.
182      */
183     public static final String ADDITIONAL_NAME = DefaultConfigurationBuilder.class
184             .getName()
185             + "/ADDITIONAL_CONFIG";
186 
187     /***
188      * Constant for the type of error events caused by optional configurations
189      * that cannot be loaded.
190      */
191     public static final int EVENT_ERR_LOAD_OPTIONAL = 51;
192 
193     /*** Constant for the name of the configuration bean factory. */
194     static final String CONFIG_BEAN_FACTORY_NAME = DefaultConfigurationBuilder.class
195             .getName()
196             + ".CONFIG_BEAN_FACTORY_NAME";
197 
198     /*** Constant for the reserved name attribute. */
199     static final String ATTR_NAME = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
200             + XMLBeanDeclaration.RESERVED_PREFIX
201             + "name"
202             + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
203 
204     /*** Constant for the name of the at attribute. */
205     static final String ATTR_ATNAME = "at";
206 
207     /*** Constant for the reserved at attribute. */
208     static final String ATTR_AT_RES = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
209             + XMLBeanDeclaration.RESERVED_PREFIX
210             + ATTR_ATNAME
211             + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
212 
213     /*** Constant for the at attribute without the reserved prefix. */
214     static final String ATTR_AT = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
215             + ATTR_ATNAME + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
216 
217     /*** Constant for the name of the optional attribute. */
218     static final String ATTR_OPTIONALNAME = "optional";
219 
220     /*** Constant for the reserved optional attribute. */
221     static final String ATTR_OPTIONAL_RES = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
222             + XMLBeanDeclaration.RESERVED_PREFIX
223             + ATTR_OPTIONALNAME
224             + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
225 
226     /*** Constant for the optional attribute without the reserved prefix. */
227     static final String ATTR_OPTIONAL = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
228             + ATTR_OPTIONALNAME + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
229 
230     /*** Constant for the file name attribute. */
231     static final String ATTR_FILENAME = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
232             + "fileName" + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
233 
234     /*** Constant for the forceCreate attribute. */
235     static final String ATTR_FORCECREATE = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
236             + XMLBeanDeclaration.RESERVED_PREFIX
237             + "forceCreate"
238             + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
239 
240     /*** Constant for the name of the header section. */
241     static final String SEC_HEADER = "header";
242 
243     /*** Constant for an expression that selects the union configurations. */
244     static final String KEY_UNION = "additional";
245 
246     /*** An array with the names of top level configuration sections.*/
247     static final String[] CONFIG_SECTIONS = {
248         "additional", "override", SEC_HEADER
249     };
250 
251     /***
252      * Constant for an expression that selects override configurations in the
253      * override section.
254      */
255     static final String KEY_OVERRIDE = "override";
256 
257     /***
258      * Constant for the key that points to the list nodes definition of the
259      * override combiner.
260      */
261     static final String KEY_OVERRIDE_LIST = SEC_HEADER
262             + ".combiner.override.list-nodes.node";
263 
264     /***
265      * Constant for the key that points to the list nodes definition of the
266      * additional combiner.
267      */
268     static final String KEY_ADDITIONAL_LIST = SEC_HEADER
269             + ".combiner.additional.list-nodes.node";
270 
271     /***
272      * Constant for the key of the result declaration. This key can point to a
273      * bean declaration, which defines properties of the resulting combined
274      * configuration.
275      */
276     static final String KEY_RESULT = SEC_HEADER + ".result";
277 
278     /*** Constant for the key of the combiner in the result declaration.*/
279     static final String KEY_COMBINER = KEY_RESULT + ".nodeCombiner";
280 
281     /*** Constant for the XML file extension. */
282     static final String EXT_XML = ".xml";
283 
284     /*** Constant for the provider for properties files. */
285     private static final ConfigurationProvider PROPERTIES_PROVIDER = new FileExtensionConfigurationProvider(
286             XMLPropertiesConfiguration.class, PropertiesConfiguration.class,
287             EXT_XML);
288 
289     /*** Constant for the provider for XML files. */
290     private static final ConfigurationProvider XML_PROVIDER = new XMLConfigurationProvider();
291 
292     /*** Constant for the provider for JNDI sources. */
293     private static final ConfigurationProvider JNDI_PROVIDER = new ConfigurationProvider(
294             JNDIConfiguration.class);
295 
296     /*** Constant for the provider for system properties. */
297     private static final ConfigurationProvider SYSTEM_PROVIDER = new ConfigurationProvider(
298             SystemConfiguration.class);
299 
300     /*** Constant for the provider for plist files. */
301     private static final ConfigurationProvider PLIST_PROVIDER = new FileExtensionConfigurationProvider(
302             "org.apache.commons.configuration.plist.XMLPropertyListConfiguration",
303             "org.apache.commons.configuration.plist.PropertyListConfiguration",
304             EXT_XML);
305 
306     /*** Constant for the provider for configuration definition files.*/
307     private static final ConfigurationProvider BUILDER_PROVIDER = new ConfigurationBuilderProvider();
308 
309     /*** An array with the names of the default tags. */
310     private static final String[] DEFAULT_TAGS =
311     {"properties", "xml", "hierarchicalXml", "jndi", "system", "plist", "configuration"};
312 
313     /*** An array with the providers for the default tags. */
314     private static final ConfigurationProvider[] DEFAULT_PROVIDERS =
315     {PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER, JNDI_PROVIDER,
316             SYSTEM_PROVIDER, PLIST_PROVIDER, BUILDER_PROVIDER};
317 
318     /***
319      * The serial version UID.
320      */
321     private static final long serialVersionUID = -3113777854714492123L;
322 
323     /*** Stores the configuration that is currently constructed.*/
324     private CombinedConfiguration constructedConfiguration;
325 
326     /*** Stores a map with the registered configuration providers. */
327     private Map providers;
328 
329     /*** Stores the base path to the configuration sources to load. */
330     private String configurationBasePath;
331 
332     /***
333      * Creates a new instance of <code>DefaultConfigurationBuilder</code>. A
334      * configuration definition file is not yet loaded. Use the diverse setter
335      * methods provided by file based configurations to specify the
336      * configuration definition file.
337      */
338     public DefaultConfigurationBuilder()
339     {
340         super();
341         providers = new HashMap();
342         registerDefaultProviders();
343         registerBeanFactory();
344         setLogger(LogFactory.getLog(getClass()));
345         addErrorLogListener();  // log errors per default
346     }
347 
348     /***
349      * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
350      * sets the specified configuration definition file.
351      *
352      * @param file the configuration definition file
353      */
354     public DefaultConfigurationBuilder(File file)
355     {
356         this();
357         setFile(file);
358     }
359 
360     /***
361      * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
362      * sets the specified configuration definition file.
363      *
364      * @param fileName the name of the configuration definition file
365      * @throws ConfigurationException if an error occurs when the file is loaded
366      */
367     public DefaultConfigurationBuilder(String fileName)
368             throws ConfigurationException
369     {
370         this();
371         setFileName(fileName);
372     }
373 
374     /***
375      * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
376      * sets the specified configuration definition file.
377      *
378      * @param url the URL to the configuration definition file
379      * @throws ConfigurationException if an error occurs when the file is loaded
380      */
381     public DefaultConfigurationBuilder(URL url) throws ConfigurationException
382     {
383         this();
384         setURL(url);
385     }
386 
387     /***
388      * Returns the base path for the configuration sources to load. This path is
389      * used to resolve relative paths in the configuration definition file.
390      *
391      * @return the base path for configuration sources
392      */
393     public String getConfigurationBasePath()
394     {
395         return (configurationBasePath != null) ? configurationBasePath
396                 : getBasePath();
397     }
398 
399     /***
400      * Sets the base path for the configuration sources to load. Normally a base
401      * path need not to be set because it is determined by the location of the
402      * configuration definition file to load. All relative pathes in this file
403      * are resolved relative to this file. Setting a base path makes sense if
404      * such relative pathes should be otherwise resolved, e.g. if the
405      * configuration file is loaded from the class path and all sub
406      * configurations it refers to are stored in a special config directory.
407      *
408      * @param configurationBasePath the new base path to set
409      */
410     public void setConfigurationBasePath(String configurationBasePath)
411     {
412         this.configurationBasePath = configurationBasePath;
413     }
414 
415     /***
416      * Adds a configuration provider for the specified tag. Whenever this tag is
417      * encountered in the configuration definition file this provider will be
418      * called to create the configuration object.
419      *
420      * @param tagName the name of the tag in the configuration definition file
421      * @param provider the provider for this tag
422      */
423     public void addConfigurationProvider(String tagName,
424             ConfigurationProvider provider)
425     {
426         if (tagName == null)
427         {
428             throw new IllegalArgumentException("Tag name must not be null!");
429         }
430         if (provider == null)
431         {
432             throw new IllegalArgumentException("Provider must not be null!");
433         }
434 
435         providers.put(tagName, provider);
436     }
437 
438     /***
439      * Removes the configuration provider for the specified tag name.
440      *
441      * @param tagName the tag name
442      * @return the removed configuration provider or <b>null</b> if none was
443      * registered for that tag
444      */
445     public ConfigurationProvider removeConfigurationProvider(String tagName)
446     {
447         return (ConfigurationProvider) providers.remove(tagName);
448     }
449 
450     /***
451      * Returns the configuration provider for the given tag.
452      *
453      * @param tagName the name of the tag
454      * @return the provider that was registered for this tag or <b>null</b> if
455      * there is none
456      */
457     public ConfigurationProvider providerForTag(String tagName)
458     {
459         return (ConfigurationProvider) providers.get(tagName);
460     }
461 
462     /***
463      * Returns the configuration provided by this builder. Loads and parses the
464      * configuration definition file and creates instances for the declared
465      * configurations.
466      *
467      * @return the configuration
468      * @throws ConfigurationException if an error occurs
469      */
470     public Configuration getConfiguration() throws ConfigurationException
471     {
472         return getConfiguration(true);
473     }
474 
475     /***
476      * Returns the configuration provided by this builder. If the boolean
477      * parameter is <b>true</b>, the configuration definition file will be
478      * loaded. It will then be parsed, and instances for the declared
479      * configurations will be created.
480      *
481      * @param load a flag whether the configuration definition file should be
482      * loaded; a value of <b>false</b> would make sense if the file has already
483      * been created or its content was manipulated using some of the property
484      * accessor methods
485      * @return the configuration
486      * @throws ConfigurationException if an error occurs
487      */
488     public CombinedConfiguration getConfiguration(boolean load)
489             throws ConfigurationException
490     {
491         if (load)
492         {
493             load();
494         }
495 
496         CombinedConfiguration result = createResultConfiguration();
497         constructedConfiguration = result;
498 
499         List overrides = fetchTopLevelOverrideConfigs();
500         overrides.addAll(fetchChildConfigs(KEY_OVERRIDE));
501         initCombinedConfiguration(result, overrides, KEY_OVERRIDE_LIST);
502 
503         List additionals = fetchChildConfigs(KEY_UNION);
504         if (!additionals.isEmpty())
505         {
506             CombinedConfiguration addConfig = new CombinedConfiguration(
507                     new UnionCombiner());
508             result.addConfiguration(addConfig, ADDITIONAL_NAME);
509             initCombinedConfiguration(addConfig, additionals,
510                     KEY_ADDITIONAL_LIST);
511         }
512 
513         return result;
514     }
515 
516     /***
517      * Creates the resulting combined configuration. This method is called by
518      * <code>getConfiguration()</code>. It checks whether the
519      * <code>header</code> section of the configuration definition file
520      * contains a <code>result</code> element. If this is the case, it will be
521      * used to initialize the properties of the newly created configuration
522      * object.
523      *
524      * @return the resulting configuration object
525      * @throws ConfigurationException if an error occurs
526      */
527     protected CombinedConfiguration createResultConfiguration()
528             throws ConfigurationException
529     {
530         XMLBeanDeclaration decl = new XMLBeanDeclaration(this, KEY_RESULT, true);
531         CombinedConfiguration result = (CombinedConfiguration) BeanHelper
532                 .createBean(decl, CombinedConfiguration.class);
533 
534         if (getMaxIndex(KEY_COMBINER) < 0)
535         {
536             // No combiner defined => set default
537             result.setNodeCombiner(new OverrideCombiner());
538         }
539 
540         return result;
541     }
542 
543     /***
544      * Initializes a combined configuration for the configurations of a specific
545      * section. This method is called for the override and for the additional
546      * section (if it exists).
547      *
548      * @param config the configuration to be initialized
549      * @param containedConfigs the list with the declaratinos of the contained
550      * configurations
551      * @param keyListNodes a list with the declaration of list nodes
552      * @throws ConfigurationException if an error occurs
553      */
554     protected void initCombinedConfiguration(CombinedConfiguration config,
555             List containedConfigs, String keyListNodes) throws ConfigurationException
556     {
557         List listNodes = getList(keyListNodes);
558         for (Iterator it = listNodes.iterator(); it.hasNext();)
559         {
560             config.getNodeCombiner().addListNode((String) it.next());
561         }
562 
563         for (Iterator it = containedConfigs.iterator(); it.hasNext();)
564         {
565             HierarchicalConfiguration conf = (HierarchicalConfiguration) it
566                     .next();
567             ConfigurationDeclaration decl = new ConfigurationDeclaration(this,
568                     conf);
569             AbstractConfiguration newConf = createConfigurationAt(decl);
570             if (newConf != null)
571             {
572                 config.addConfiguration(newConf, decl.getConfiguration()
573                         .getString(ATTR_NAME), decl.getAt());
574             }
575         }
576     }
577 
578     /***
579      * Registers the default configuration providers supported by this class.
580      * This method will be called during initialization. It registers
581      * configuration providers for the tags that are supported by default.
582      */
583     protected void registerDefaultProviders()
584     {
585         for (int i = 0; i < DEFAULT_TAGS.length; i++)
586         {
587             addConfigurationProvider(DEFAULT_TAGS[i], DEFAULT_PROVIDERS[i]);
588         }
589     }
590 
591     /***
592      * Performs interpolation. This method will not only take this configuration
593      * instance into account (which is the one that loaded the configuration
594      * definition file), but also the so far constructed combined configuration.
595      * So variables can be used that point to properties that are defined in
596      * configuration sources loaded by this builder.
597      *
598      * @param value the value to be interpolated
599      * @return the interpolated value
600      */
601     protected Object interpolate(Object value)
602     {
603         Object result = super.interpolate(value);
604         if (constructedConfiguration != null)
605         {
606             result = constructedConfiguration.interpolate(result);
607         }
608         return result;
609     }
610 
611     protected void fireError(int type, String propName, Object propValue,
612             Throwable ex)
613     {
614         // This method is only overridden to fix a mysterious MethodNotFound
615         // error in the test cases when run under a JDK 1.3.
616         super.fireError(type, propName, propValue, ex);
617     }
618 
619     /***
620      * Creates a configuration object from the specified configuration
621      * declaration.
622      *
623      * @param decl the configuration declaration
624      * @return the new configuration object
625      * @throws ConfigurationException if an error occurs
626      */
627     private AbstractConfiguration createConfigurationAt(
628             ConfigurationDeclaration decl) throws ConfigurationException
629     {
630         try
631         {
632             return (AbstractConfiguration) BeanHelper.createBean(decl);
633         }
634         catch (Exception ex)
635         {
636             // redirect to configuration exceptions
637             throw new ConfigurationException(ex);
638         }
639     }
640 
641     /***
642      * Returns a list with <code>SubnodeConfiguration</code> objects for the
643      * child nodes of the specified configuration node.
644      *
645      * @param node the start node
646      * @return a list with subnode configurations for the node's children
647      */
648     private List fetchChildConfigs(ConfigurationNode node)
649     {
650         List children = node.getChildren();
651         List result = new ArrayList(children.size());
652         for (Iterator it = children.iterator(); it.hasNext();)
653         {
654             result.add(createSubnodeConfiguration((Node) it.next()));
655         }
656         return result;
657     }
658 
659     /***
660      * Returns a list with <code>SubnodeConfiguration</code> objects for the
661      * child nodes of the node specified by the given key.
662      *
663      * @param key the key (must define exactly one node)
664      * @return a list with subnode configurations for the node's children
665      */
666     private List fetchChildConfigs(String key)
667     {
668         List nodes = fetchNodeList(key);
669         if (nodes.size() > 0)
670         {
671             return fetchChildConfigs((ConfigurationNode) nodes.get(0));
672         }
673         else
674         {
675             return Collections.EMPTY_LIST;
676         }
677     }
678 
679     /***
680      * Finds the override configurations that are defined as top level elements
681      * in the configuration definition file. This method will fetch the child
682      * elements of the root node and remove the nodes that represent other
683      * configuration sections. The remaining nodes are treated as definitions
684      * for override configurations.
685      *
686      * @return a list with subnode configurations for the top level override
687      * configurations
688      */
689     private List fetchTopLevelOverrideConfigs()
690     {
691         List configs = fetchChildConfigs(getRootNode());
692         for (Iterator it = configs.iterator(); it.hasNext();)
693         {
694             String nodeName = ((SubnodeConfiguration) it.next()).getRootNode()
695                     .getName();
696             for (int i = 0; i < CONFIG_SECTIONS.length; i++)
697             {
698                 if (CONFIG_SECTIONS[i].equals(nodeName))
699                 {
700                     it.remove();
701                     break;
702                 }
703             }
704         }
705         return configs;
706     }
707 
708     /***
709      * Registers the bean factory used by this class if necessary. This method
710      * is called by the constructor to ensure that the required bean factory is
711      * available.
712      */
713     private void registerBeanFactory()
714     {
715         synchronized (getClass())
716         {
717             if (!BeanHelper.registeredFactoryNames().contains(
718                     CONFIG_BEAN_FACTORY_NAME))
719             {
720                 BeanHelper.registerBeanFactory(CONFIG_BEAN_FACTORY_NAME,
721                         new ConfigurationBeanFactory());
722             }
723         }
724     }
725 
726     /***
727      * <p>
728      * A base class for creating and initializing configuration sources.
729      * </p>
730      * <p>
731      * Concrete sub classes of this base class are responsible for creating
732      * specific <code>Configuration</code> objects for the tags in the
733      * configuration definition file. The configuration factory will parse the
734      * definition file and try to find a matching
735      * <code>ConfigurationProvider</code> for each encountered tag. This
736      * provider is then asked to create a corresponding
737      * <code>Configuration</code> object. It is up to a concrete
738      * implementation how this object is created and initialized.
739      * </p>
740      * <p>
741      * Note that at the moment only configuration classes derived from
742      * <code>{@link AbstractConfiguration}</code> are supported.
743      * </p>
744      */
745     public static class ConfigurationProvider extends DefaultBeanFactory
746     {
747         /*** Stores the class of the configuration to be created. */
748         private Class configurationClass;
749 
750         /*** Stores the name of the configuration class to be created.*/
751         private String configurationClassName;
752 
753         /***
754          * Creates a new uninitialized instance of
755          * <code>ConfigurationProvider</code>.
756          */
757         public ConfigurationProvider()
758         {
759             this((Class) null);
760         }
761 
762         /***
763          * Creates a new instance of <code>ConfigurationProvider</code> and
764          * sets the class of the configuration created by this provider.
765          *
766          * @param configClass the configuration class
767          */
768         public ConfigurationProvider(Class configClass)
769         {
770             setConfigurationClass(configClass);
771         }
772 
773         /***
774          * Creates a new instance of <code>ConfigurationProvider</code> and
775          * sets the name of the class of the configuration created by this
776          * provider.
777          *
778          * @param configClassName the name of the configuration class
779          * @since 1.4
780          */
781         public ConfigurationProvider(String configClassName)
782         {
783             setConfigurationClassName(configClassName);
784         }
785 
786         /***
787          * Returns the class of the configuration returned by this provider.
788          *
789          * @return the class of the provided configuration
790          */
791         public Class getConfigurationClass()
792         {
793             return configurationClass;
794         }
795 
796         /***
797          * Sets the class of the configuration returned by this provider.
798          *
799          * @param configurationClass the configuration class
800          */
801         public void setConfigurationClass(Class configurationClass)
802         {
803             this.configurationClass = configurationClass;
804         }
805 
806         /***
807          * Returns the name of the configuration class returned by this
808          * provider.
809          *
810          * @return the configuration class name
811          * @since 1.4
812          */
813         public String getConfigurationClassName()
814         {
815             return configurationClassName;
816         }
817 
818         /***
819          * Sets the name of the configuration class returned by this provider.
820          *
821          * @param configurationClassName the name of the configuration class
822          * @since 1.4
823          */
824         public void setConfigurationClassName(String configurationClassName)
825         {
826             this.configurationClassName = configurationClassName;
827         }
828 
829         /***
830          * Returns the configuration. This method is called to fetch the
831          * configuration from the provider. This implementation will call the
832          * inherited <code>{@link
833          * org.apache.commons.configuration.beanutils.DefaultBeanFactory#createBean(Class, BeanDeclaration, Object)
834          * createBean()}</code> method to create a new instance of the
835          * configuration class.
836          *
837          * @param decl the bean declaration with initialization parameters for
838          * the configuration
839          * @return the new configuration object
840          * @throws Exception if an error occurs
841          */
842         public AbstractConfiguration getConfiguration(
843                 ConfigurationDeclaration decl) throws Exception
844         {
845             return (AbstractConfiguration) createBean(fetchConfigurationClass(),
846                     decl, null);
847         }
848 
849         /***
850          * Returns an uninitialized configuration of the represented type. This
851          * method will be called for optional configurations when the
852          * <code>getConfiguration()</code> method caused an error and the
853          * <code>forceCreate</code> attribute is set. A concrete sub class can
854          * here try to create an uninitialized, empty configuration, which may
855          * be possible if the error was created during initialization. This base
856          * implementation just returns <b>null</b>.
857          *
858          * @param decl the bean declaration with initialization parameters for
859          * the configuration
860          * @return the new configuration object
861          * @throws Exception if an error occurs
862          * @since 1.4
863          */
864         public AbstractConfiguration getEmptyConfiguration(
865                 ConfigurationDeclaration decl) throws Exception
866         {
867             return null;
868         }
869 
870         /***
871          * Returns the configuration class supported by this provider. If a
872          * class object was set, it is returned. Otherwise the method tries to
873          * resolve the class name.
874          *
875          * @return the class of the configuration to be created
876          * @since 1.4
877          */
878         protected synchronized Class fetchConfigurationClass() throws Exception
879         {
880             if (getConfigurationClass() == null)
881             {
882                 setConfigurationClass(loadClass(getConfigurationClassName()));
883             }
884             return getConfigurationClass();
885         }
886 
887         /***
888          * Loads the class with the specified name dynamically. If the class's
889          * name is <b>null</b>, <b>null</b> will also be returned.
890          *
891          * @param className the name of the class to be loaded
892          * @return the class object
893          * @throws ClassNotFoundException if class loading fails
894          * @since 1.4
895          */
896         protected Class loadClass(String className)
897                 throws ClassNotFoundException
898         {
899             return (className != null) ? Class.forName(className, true,
900                     getClass().getClassLoader()) : null;
901         }
902     }
903 
904     /***
905      * <p>
906      * A specialized <code>BeanDeclaration</code> implementation that
907      * represents the declaration of a configuration source.
908      * </p>
909      * <p>
910      * Instances of this class are able to extract all information about a
911      * configuration source from the configuration definition file. The
912      * declaration of a configuration source is very similar to a bean
913      * declaration processed by <code>XMLBeanDeclaration</code>. There are
914      * very few differences, e.g. some reserved attributes like
915      * <code>optional</code> and <code>at</code> and the fact that a bean
916      * factory is never needed.
917      * </p>
918      */
919     public static class ConfigurationDeclaration extends XMLBeanDeclaration
920     {
921         /*** Stores a reference to the associated configuration builder. */
922         private DefaultConfigurationBuilder configurationBuilder;
923 
924         /***
925          * Creates a new instance of <code>ConfigurationDeclaration</code> and
926          * initializes it.
927          *
928          * @param builder the associated configuration builder
929          * @param config the configuration this declaration is based onto
930          */
931         public ConfigurationDeclaration(DefaultConfigurationBuilder builder,
932                 HierarchicalConfiguration config)
933         {
934             super(config);
935             configurationBuilder = builder;
936         }
937 
938         /***
939          * Returns the associated configuration builder.
940          *
941          * @return the configuration builder
942          */
943         public DefaultConfigurationBuilder getConfigurationBuilder()
944         {
945             return configurationBuilder;
946         }
947 
948         /***
949          * Returns the value of the <code>at</code> attribute.
950          *
951          * @return the value of the <code>at</code> attribute (can be <b>null</b>)
952          */
953         public String getAt()
954         {
955             String result = this.getConfiguration().getString(ATTR_AT_RES);
956             return (result == null) ? this.getConfiguration().getString(ATTR_AT)
957                     : result;
958         }
959 
960         /***
961          * Returns a flag whether this is an optional configuration.
962          *
963          * @return a flag if this declaration points to an optional
964          * configuration
965          */
966         public boolean isOptional()
967         {
968             Boolean value = this.getConfiguration().getBoolean(ATTR_OPTIONAL_RES,
969                     null);
970             if (value == null)
971             {
972                 value = this.getConfiguration().getBoolean(ATTR_OPTIONAL,
973                         Boolean.FALSE);
974             }
975             return value.booleanValue();
976         }
977 
978         /***
979          * Returns a flag whether this configuration should always be created
980          * and added to the resulting combined configuration. This flag is
981          * evaluated only for optional configurations whose normal creation has
982          * caused an error. If for such a configuration the
983          * <code>forceCreate</code> attribute is set and the corresponding
984          * configuration provider supports this mode, an empty configuration
985          * will be created and added to the resulting combined configuration.
986          *
987          * @return the value of the <code>forceCreate</code> attribute
988          * @since 1.4
989          */
990         public boolean isForceCreate()
991         {
992             return this.getConfiguration().getBoolean(ATTR_FORCECREATE, false);
993         }
994 
995         /***
996          * Returns the name of the bean factory. For configuration source
997          * declarations always a reserved factory is used. This factory's name
998          * is returned by this implementation.
999          *
1000          * @return the name of the bean factory
1001          */
1002         public String getBeanFactoryName()
1003         {
1004             return CONFIG_BEAN_FACTORY_NAME;
1005         }
1006 
1007         /***
1008          * Returns the bean's class name. This implementation will always return
1009          * <b>null</b>.
1010          *
1011          * @return the name of the bean's class
1012          */
1013         public String getBeanClassName()
1014         {
1015             return null;
1016         }
1017 
1018         /***
1019          * Checks whether the given node is reserved. This method will take
1020          * further reserved attributes into account
1021          *
1022          * @param nd the node
1023          * @return a flag whether this node is reserved
1024          */
1025         protected boolean isReservedNode(ConfigurationNode nd)
1026         {
1027             if (super.isReservedNode(nd))
1028             {
1029                 return true;
1030             }
1031 
1032             return nd.isAttribute()
1033                     && ((ATTR_ATNAME.equals(nd.getName()) && nd.getParentNode()
1034                             .getAttributeCount(RESERVED_PREFIX + ATTR_ATNAME) == 0) || (ATTR_OPTIONALNAME
1035                             .equals(nd.getName()) && nd.getParentNode()
1036                             .getAttributeCount(RESERVED_PREFIX + ATTR_OPTIONALNAME) == 0));
1037         }
1038 
1039         /***
1040          * Performs interpolation. This implementation will delegate
1041          * interpolation to the configuration builder, which takes care that the
1042          * currently constructed configuration is taken into account, too.
1043          *
1044          * @param value the value to be interpolated
1045          * @return the interpolated value
1046          */
1047         protected Object interpolate(Object value)
1048         {
1049             return getConfigurationBuilder().interpolate(value);
1050         }
1051     }
1052 
1053     /***
1054      * A specialized <code>BeanFactory</code> implementation that handles
1055      * configuration declarations. This class will retrieve the correct
1056      * configuration provider and delegate the task of creating the
1057      * configuration to this object.
1058      */
1059     static class ConfigurationBeanFactory implements BeanFactory
1060     {
1061         /***
1062          * Creates an instance of a bean class. This implementation expects that
1063          * the passed in bean declaration is a declaration for a configuration.
1064          * It will determine the responsible configuration provider and delegate
1065          * the call to this instance. If creation of the configuration fails
1066          * and the <code>optional</code> attribute is set, the exception will
1067          * be ignored. If the <code>forceCreate</code> attribute is set, too,
1068          * the provider is asked to create an empty configuration. A return
1069          * value of <b>null</b> means that no configuration could be created.
1070          *
1071          * @param beanClass the bean class (will be ignored)
1072          * @param data the declaration
1073          * @param param an additional parameter (will be ignored)
1074          * @return the newly created configuration
1075          * @throws Exception if an error occurs
1076          */
1077         public Object createBean(Class beanClass, BeanDeclaration data,
1078                 Object param) throws Exception
1079         {
1080             ConfigurationDeclaration decl = (ConfigurationDeclaration) data;
1081             String tagName = decl.getNode().getName();
1082             ConfigurationProvider provider = decl.getConfigurationBuilder()
1083                     .providerForTag(tagName);
1084             if (provider == null)
1085             {
1086                 throw new ConfigurationRuntimeException(
1087                         "No ConfigurationProvider registered for tag "
1088                                 + tagName);
1089             }
1090 
1091             try
1092             {
1093                 return provider.getConfiguration(decl);
1094             }
1095             catch (Exception ex)
1096             {
1097                 // If this is an optional configuration, ignore the exception
1098                 if (!decl.isOptional())
1099                 {
1100                     throw ex;
1101                 }
1102                 else
1103                 {
1104                     // Notify registered error listeners
1105                     decl.getConfigurationBuilder().fireError(
1106                             EVENT_ERR_LOAD_OPTIONAL,
1107                             decl.getConfiguration().getString(ATTR_NAME), null,
1108                             ex);
1109 
1110                     if (decl.isForceCreate())
1111                     {
1112                         try
1113                         {
1114                             return provider.getEmptyConfiguration(decl);
1115                         }
1116                         catch (Exception ex2)
1117                         {
1118                             // Ignore exception, return null in this case
1119                             ;
1120                         }
1121                     }
1122                     return null;
1123                 }
1124             }
1125         }
1126 
1127         /***
1128          * Returns the default class for this bean factory.
1129          *
1130          * @return the default class
1131          */
1132         public Class getDefaultBeanClass()
1133         {
1134             // Here some valid class must be returned, otherwise BeanHelper
1135             // will complain that the bean's class cannot be determined
1136             return Configuration.class;
1137         }
1138     }
1139 
1140     /***
1141      * A specialized provider implementation that deals with file based
1142      * configurations. Ensures that the base path is correctly set and that the
1143      * load() method gets called.
1144      */
1145     public static class FileConfigurationProvider extends ConfigurationProvider
1146     {
1147         /***
1148          * Creates a new instance of <code>FileConfigurationProvider</code>.
1149          */
1150         public FileConfigurationProvider()
1151         {
1152             super();
1153         }
1154 
1155         /***
1156          * Creates a new instance of <code>FileConfigurationProvider</code>
1157          * and sets the configuration class.
1158          *
1159          * @param configClass the class for the configurations to be created
1160          */
1161         public FileConfigurationProvider(Class configClass)
1162         {
1163             super(configClass);
1164         }
1165 
1166         /***
1167          * Creates a new instance of <code>FileConfigurationProvider</code>
1168          * and sets the configuration class name.
1169          *
1170          * @param configClassName the name of the configuration to be created
1171          * @since 1.4
1172          */
1173         public FileConfigurationProvider(String configClassName)
1174         {
1175             super(configClassName);
1176         }
1177 
1178         /***
1179          * Creates the configuration. After that <code>load()</code> will be
1180          * called. If this configuration is marked as optional, exceptions will
1181          * be ignored.
1182          *
1183          * @param decl the declaration
1184          * @return the new configuration
1185          * @throws Exception if an error occurs
1186          */
1187         public AbstractConfiguration getConfiguration(
1188                 ConfigurationDeclaration decl) throws Exception
1189         {
1190             AbstractConfiguration result = getEmptyConfiguration(decl);
1191             ((FileConfiguration) result).load();
1192             return result;
1193         }
1194 
1195         /***
1196          * Returns an uninitialized file configuration. This method will be
1197          * called for optional configurations when the
1198          * <code>getConfiguration()</code> method caused an error and the
1199          * <code>forceCreate</code> attribute is set. It will create the
1200          * configuration of the represented type, but the <code>load()</code>
1201          * method won't be called. This way non-existing configuration files can
1202          * be handled gracefully: If loading a the file fails, an empty
1203          * configuration will be created that is already configured with the
1204          * correct file name.
1205          *
1206          * @param decl the bean declaration with initialization parameters for
1207          * the configuration
1208          * @return the new configuration object
1209          * @throws Exception if an error occurs
1210          * @since 1.4
1211          */
1212         public AbstractConfiguration getEmptyConfiguration(
1213                 ConfigurationDeclaration decl) throws Exception
1214         {
1215             return super.getConfiguration(decl);
1216         }
1217 
1218         /***
1219          * Initializes the bean instance. Ensures that the file configuration's
1220          * base path will be initialized with the base path of the factory so
1221          * that relative path names can be correctly resolved.
1222          *
1223          * @param bean the bean to be initialized
1224          * @param data the declaration
1225          * @throws Exception if an error occurs
1226          */
1227         protected void initBeanInstance(Object bean, BeanDeclaration data)
1228                 throws Exception
1229         {
1230             FileConfiguration config = (FileConfiguration) bean;
1231             config.setBasePath(((ConfigurationDeclaration) data)
1232                     .getConfigurationBuilder().getConfigurationBasePath());
1233             super.initBeanInstance(bean, data);
1234         }
1235     }
1236 
1237     /***
1238      * A specialized configuration provider for XML configurations. This
1239      * implementation acts like a <code>FileConfigurationProvider</code>, but
1240      * it will copy all entity IDs that have been registered for the
1241      * configuration builder to the new XML configuration before it is loaded.
1242      */
1243     static class XMLConfigurationProvider extends FileConfigurationProvider
1244     {
1245         /***
1246          * Creates a new instance of <code>XMLConfigurationProvider</code>.
1247          */
1248         public XMLConfigurationProvider()
1249         {
1250             super(XMLConfiguration.class);
1251         }
1252 
1253         /***
1254          * Returns a new empty configuration instance. This implementation
1255          * performs some additional initialization specific to XML
1256          * configurations.
1257          *
1258          * @param decl the configuration declaration
1259          * @return the new configuration
1260          * @throws Exception if an error occurs
1261          */
1262         public AbstractConfiguration getEmptyConfiguration(
1263                 ConfigurationDeclaration decl) throws Exception
1264         {
1265             XMLConfiguration config = (XMLConfiguration) super
1266                     .getEmptyConfiguration(decl);
1267 
1268             // copy the registered entities
1269             DefaultConfigurationBuilder builder = decl
1270                     .getConfigurationBuilder();
1271             config.getRegisteredEntities().putAll(
1272                     builder.getRegisteredEntities());
1273             return config;
1274         }
1275     }
1276 
1277     /***
1278      * A specialized configuration provider for file based configurations that
1279      * can handle configuration sources whose concrete type depends on the
1280      * extension of the file to be loaded. One example is the
1281      * <code>properties</code> tag: if the file ends with ".xml" a
1282      * XMLPropertiesConfiguration object must be created, otherwise a
1283      * PropertiesConfiguration object.
1284      */
1285     static class FileExtensionConfigurationProvider extends
1286             FileConfigurationProvider
1287     {
1288         /***
1289          * Stores the class to be created when the file extension matches.
1290          */
1291         private Class matchingClass;
1292 
1293         /***
1294          * Stores the name of the class to be created when the file extension
1295          * matches.
1296          */
1297         private String matchingClassName;
1298 
1299         /***
1300          * Stores the class to be created when the file extension does not
1301          * match.
1302          */
1303         private Class defaultClass;
1304 
1305         /***
1306          * Stores the name of the class to be created when the file extension
1307          * does not match.
1308          */
1309         private String defaultClassName;
1310 
1311         /*** Stores the file extension to be checked against. */
1312         private String fileExtension;
1313 
1314         /***
1315          * Creates a new instance of
1316          * <code>FileExtensionConfigurationProvider</code> and initializes it.
1317          *
1318          * @param matchingClass the class to be created when the file extension
1319          * matches
1320          * @param defaultClass the class to be created when the file extension
1321          * does not match
1322          * @param extension the file extension to be checked agains
1323          */
1324         public FileExtensionConfigurationProvider(Class matchingClass,
1325                 Class defaultClass, String extension)
1326         {
1327             this.matchingClass = matchingClass;
1328             this.defaultClass = defaultClass;
1329             fileExtension = extension;
1330         }
1331 
1332         /***
1333          * Creates a new instance of
1334          * <code>FileExtensionConfigurationProvider</code> and initializes it
1335          * with the names of the classes to be created.
1336          *
1337          * @param matchingClassName the name of the class to be created when the
1338          * file extension matches
1339          * @param defaultClassName the name of the class to be created when the
1340          * file extension does not match
1341          * @param extension the file extension to be checked against
1342          * @since 1.4
1343          */
1344         public FileExtensionConfigurationProvider(String matchingClassName,
1345                 String defaultClassName, String extension)
1346         {
1347             this.matchingClassName = matchingClassName;
1348             this.defaultClassName = defaultClassName;
1349             fileExtension = extension;
1350         }
1351 
1352         /***
1353          * Returns the matching class object, no matter whether it was defined
1354          * as a class or as a class name.
1355          *
1356          * @return the matching class object
1357          * @throws Exception if an error occurs
1358          * @since 1.4
1359          */
1360         protected synchronized Class fetchMatchingClass() throws Exception
1361         {
1362             if (matchingClass == null)
1363             {
1364                 matchingClass = loadClass(matchingClassName);
1365             }
1366             return matchingClass;
1367         }
1368 
1369         /***
1370          * Returns the default class object, no matter whether it was defined as
1371          * a class or as a class name.
1372          *
1373          * @return the default class object
1374          * @throws Exception if an error occurs
1375          * @since 1.4
1376          */
1377         protected synchronized Class fetchDefaultClass() throws Exception
1378         {
1379             if (defaultClass == null)
1380             {
1381                 defaultClass = loadClass(defaultClassName);
1382             }
1383             return defaultClass;
1384         }
1385 
1386         /***
1387          * Creates the configuration object. The class is determined by the file
1388          * name's extension.
1389          *
1390          * @param beanClass the class
1391          * @param data the bean declaration
1392          * @return the new bean
1393          * @throws Exception if an error occurs
1394          */
1395         protected Object createBeanInstance(Class beanClass,
1396                 BeanDeclaration data) throws Exception
1397         {
1398             String fileName = ((ConfigurationDeclaration) data)
1399                     .getConfiguration().getString(ATTR_FILENAME);
1400             if (fileName != null
1401                     && fileName.toLowerCase().trim().endsWith(fileExtension))
1402             {
1403                 return super.createBeanInstance(fetchMatchingClass(), data);
1404             }
1405             else
1406             {
1407                 return super.createBeanInstance(fetchDefaultClass(), data);
1408             }
1409         }
1410     }
1411 
1412     /***
1413      * A specialized configuration provider class that allows to include other
1414      * configuration definition files.
1415      */
1416     static class ConfigurationBuilderProvider extends ConfigurationProvider
1417     {
1418         /***
1419          * Creates a new instance of <code>ConfigurationBuilderProvider</code>.
1420          */
1421         public ConfigurationBuilderProvider()
1422         {
1423             super(DefaultConfigurationBuilder.class);
1424         }
1425 
1426         /***
1427          * Creates the configuration. First creates a configuration builder
1428          * object. Then returns the configuration created by this builder.
1429          *
1430          * @param decl the configuration declaration
1431          * @return the configuration
1432          * @exception Exception if an error occurs
1433          */
1434         public AbstractConfiguration getConfiguration(
1435                 ConfigurationDeclaration decl) throws Exception
1436         {
1437             DefaultConfigurationBuilder builder = (DefaultConfigurationBuilder) super
1438                     .getConfiguration(decl);
1439             return builder.getConfiguration(true);
1440         }
1441 
1442         /***
1443          * Returns an empty configuration in case of an optional configuration
1444          * could not be created. This implementation returns an empty combined
1445          * configuration.
1446          *
1447          * @param decl the configuration declaration
1448          * @return the configuration
1449          * @exception Exception if an error occurs
1450          * @since 1.4
1451          */
1452         public AbstractConfiguration getEmptyConfiguration(
1453                 ConfigurationDeclaration decl) throws Exception
1454         {
1455             return new CombinedConfiguration();
1456         }
1457     }
1458 }