Source Code Cross Referenced for DefaultConfigurationBuilder.java in  » Library » Apache-commons-configuration-1.4-src » org » apache » commons » configuration » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache commons configuration 1.4 src » org.apache.commons.configuration 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.commons.configuration;
0018:
0019:        import java.io.File;
0020:        import java.net.URL;
0021:        import java.util.ArrayList;
0022:        import java.util.Collections;
0023:        import java.util.HashMap;
0024:        import java.util.Iterator;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:
0028:        import org.apache.commons.configuration.beanutils.BeanDeclaration;
0029:        import org.apache.commons.configuration.beanutils.BeanFactory;
0030:        import org.apache.commons.configuration.beanutils.BeanHelper;
0031:        import org.apache.commons.configuration.beanutils.DefaultBeanFactory;
0032:        import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;
0033:        import org.apache.commons.configuration.tree.ConfigurationNode;
0034:        import org.apache.commons.configuration.tree.DefaultExpressionEngine;
0035:        import org.apache.commons.configuration.tree.OverrideCombiner;
0036:        import org.apache.commons.configuration.tree.UnionCombiner;
0037:
0038:        /**
0039:         * <p>
0040:         * A factory class that creates a composite configuration from an XML based
0041:         * <em>configuration definition file</em>.
0042:         * </p>
0043:         * <p>
0044:         * This class provides an easy and flexible means for loading multiple
0045:         * configuration sources and combining the results into a single configuration
0046:         * object. The sources to be loaded are defined in an XML document that can
0047:         * contain certain tags representing the different supported configuration
0048:         * classes. If such a tag is found, the corresponding <code>Configuration</code>
0049:         * class is instantiated and initialized using the classes of the
0050:         * <code>beanutils</code> package (namely
0051:         * <code>{@link org.apache.commons.configuration.beanutils.XMLBeanDeclaration XMLBeanDeclaration}</code>
0052:         * will be used to extract the configuration's initialization parameters, which
0053:         * allows for complex initialization szenarios).
0054:         * </p>
0055:         * <p>
0056:         * It is also possible to add custom tags to the configuration definition file.
0057:         * For this purpose register your own <code>ConfigurationProvider</code>
0058:         * implementation for your tag using the <code>addConfigurationProvider()</code>
0059:         * method. This provider will then be called when the corresponding custom tag
0060:         * is detected. For the default configuration classes providers are already
0061:         * registered.
0062:         * </p>
0063:         * <p>
0064:         * The configuration definition file has the following basic structure:
0065:         * </p>
0066:         * <p>
0067:         *
0068:         * <pre>
0069:         * &lt;configuration&gt;
0070:         *   &lt;header&gt;
0071:         *     &lt;!-- Optional meta information about the composite configuration --&gt;
0072:         *   &lt;/header&gt;
0073:         *   &lt;override&gt;
0074:         *     &lt;!-- Declarations for override configurations --&gt;
0075:         *   &lt;/override&gt;
0076:         *   &lt;additional&gt;
0077:         *     &lt;!-- Declarations for union configurations --&gt;
0078:         *   &lt;/additional&gt;
0079:         * &lt;/configuration&gt;
0080:         * </pre>
0081:         *
0082:         * </p>
0083:         * <p>
0084:         * The name of the root element (here <code>configuration</code>) is
0085:         * arbitrary. There are two sections (both of them are optional) for declaring
0086:         * <em>override</em> and <em>additional</em> configurations. Configurations
0087:         * in the former section are evaluated in the order of their declaration, and
0088:         * properties of configurations declared earlier hide those of configurations
0089:         * declared later. Configurations in the latter section are combined to a union
0090:         * configuration, i.e. all of their properties are added to a large hierarchical
0091:         * configuration. Configuration declarations that occur as direct children of
0092:         * the root element are treated as override declarations.
0093:         * </p>
0094:         * <p>
0095:         * Each configuration declaration consists of a tag whose name is associated
0096:         * with a <code>ConfigurationProvider</code>. This can be one of the
0097:         * pre-defined tags like <code>properties</code>, or <code>xml</code>, or
0098:         * a custom tag, for which a configuration provider was registered. Attributes
0099:         * and sub elements with specific initialization parameters can be added. There
0100:         * are some reserved attributes with a special meaning that can be used in every
0101:         * configuration declaration:
0102:         * </p>
0103:         * <p>
0104:         * <table border="1">
0105:         * <tr>
0106:         * <th>Attribute</th>
0107:         * <th>Meaning</th>
0108:         * </tr>
0109:         * <tr>
0110:         * <td valign="top"><code>config-name</code></td>
0111:         * <td>Allows to specify a name for this configuration. This name can be used
0112:         * to obtain a reference to the configuration from the resulting combined
0113:         * configuration (see below).</td>
0114:         * </tr>
0115:         * <tr>
0116:         * <td valign="top"><code>config-at</code></td>
0117:         * <td>With this attribute an optional prefix can be specified for the
0118:         * properties of the corresponding configuration.</td>
0119:         * </tr>
0120:         * <tr>
0121:         * <td valign="top"><code>config-optional</code></td>
0122:         * <td>Declares a configuration as optional. This means that errors that occur
0123:         * when creating the configuration are silently ignored.</td>
0124:         * </tr>
0125:         * </table>
0126:         * </p>
0127:         * <p>
0128:         * The optional <em>header</em> section can contain some meta data about the
0129:         * created configuration itself. For instance, it is possible to set further
0130:         * properties of the <code>NodeCombiner</code> objects used for constructing
0131:         * the resulting configuration.
0132:         * </p>
0133:         * <p>
0134:         * The configuration object returned by this builder is an instance of the
0135:         * <code>{@link CombinedConfiguration}</code> class. The return value of the
0136:         * <code>getConfiguration()</code> method can be casted to this type, and the
0137:         * <code>getConfiguration(boolean)</code> method directly declares
0138:         * <code>CombinedConfiguration</code> as return type. This allows for
0139:         * convenient access to the configuration objects maintained by the combined
0140:         * configuration (e.g. for updates of single configuration objects). It has also
0141:         * the advantage that the properties stored in all declared configuration
0142:         * objects are collected and transformed into a single hierarchical structure,
0143:         * which can be accessed using different expression engines.
0144:         * </p>
0145:         * <p>
0146:         * All declared override configurations are directly added to the resulting
0147:         * combined configuration. If they are given names (using the
0148:         * <code>config-name</code> attribute), they can directly be accessed using
0149:         * the <code>getConfiguration(String)</code> method of
0150:         * <code>CombinedConfiguration</code>. The additional configurations are
0151:         * alltogether added to another combined configuration, which uses a union
0152:         * combiner. Then this union configuration is added to the resulting combined
0153:         * configuration under the name defined by the <code>ADDITIONAL_NAME</code>
0154:         * constant.
0155:         * </p>
0156:         * <p>
0157:         * Implementation note: This class is not thread-safe. Especially the
0158:         * <code>getConfiguration()</code> methods should be called by a single thread
0159:         * only.
0160:         * </p>
0161:         *
0162:         * @since 1.3
0163:         * @author <a
0164:         * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons
0165:         * Configuration team</a>
0166:         * @version $Id: DefaultConfigurationBuilder.java 507219 2007-02-13 21:02:09Z oheger $
0167:         */
0168:        public class DefaultConfigurationBuilder extends XMLConfiguration
0169:                implements  ConfigurationBuilder {
0170:            /**
0171:             * Constant for the name of the additional configuration. If the
0172:             * configuration definition file contains an <code>additional</code>
0173:             * section, a special union configuration is created and added under this
0174:             * name to the resulting combined configuration.
0175:             */
0176:            public static final String ADDITIONAL_NAME = DefaultConfigurationBuilder.class
0177:                    .getName()
0178:                    + "/ADDITIONAL_CONFIG";
0179:
0180:            /** Constant for the name of the configuration bean factory. */
0181:            static final String CONFIG_BEAN_FACTORY_NAME = DefaultConfigurationBuilder.class
0182:                    .getName()
0183:                    + ".CONFIG_BEAN_FACTORY_NAME";
0184:
0185:            /** Constant for the reserved name attribute. */
0186:            static final String ATTR_NAME = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0187:                    + XMLBeanDeclaration.RESERVED_PREFIX
0188:                    + "name"
0189:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0190:
0191:            /** Constant for the name of the at attribute. */
0192:            static final String ATTR_ATNAME = "at";
0193:
0194:            /** Constant for the reserved at attribute. */
0195:            static final String ATTR_AT_RES = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0196:                    + XMLBeanDeclaration.RESERVED_PREFIX
0197:                    + ATTR_ATNAME
0198:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0199:
0200:            /** Constant for the at attribute without the reserved prefix. */
0201:            static final String ATTR_AT = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0202:                    + ATTR_ATNAME
0203:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0204:
0205:            /** Constant for the name of the optional attribute. */
0206:            static final String ATTR_OPTIONALNAME = "optional";
0207:
0208:            /** Constant for the reserved optional attribute. */
0209:            static final String ATTR_OPTIONAL_RES = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0210:                    + XMLBeanDeclaration.RESERVED_PREFIX
0211:                    + ATTR_OPTIONALNAME
0212:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0213:
0214:            /** Constant for the optional attribute without the reserved prefix. */
0215:            static final String ATTR_OPTIONAL = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0216:                    + ATTR_OPTIONALNAME
0217:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0218:
0219:            /** Constant for the file name attribute. */
0220:            static final String ATTR_FILENAME = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0221:                    + "fileName"
0222:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0223:
0224:            /** Constant for the forceCreate attribute. */
0225:            static final String ATTR_FORCECREATE = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
0226:                    + XMLBeanDeclaration.RESERVED_PREFIX
0227:                    + "forceCreate"
0228:                    + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
0229:
0230:            /** Constant for the name of the header section. */
0231:            static final String SEC_HEADER = "header";
0232:
0233:            /** Constant for an expression that selects the union configurations. */
0234:            static final String KEY_UNION = "additional";
0235:
0236:            /** An array with the names of top level configuration sections.*/
0237:            static final String[] CONFIG_SECTIONS = { "additional", "override",
0238:                    SEC_HEADER };
0239:
0240:            /**
0241:             * Constant for an expression that selects override configurations in the
0242:             * override section.
0243:             */
0244:            static final String KEY_OVERRIDE = "override";
0245:
0246:            /**
0247:             * Constant for the key that points to the list nodes definition of the
0248:             * override combiner.
0249:             */
0250:            static final String KEY_OVERRIDE_LIST = SEC_HEADER
0251:                    + ".combiner.override.list-nodes.node";
0252:
0253:            /**
0254:             * Constant for the key that points to the list nodes definition of the
0255:             * additional combiner.
0256:             */
0257:            static final String KEY_ADDITIONAL_LIST = SEC_HEADER
0258:                    + ".combiner.additional.list-nodes.node";
0259:
0260:            /**
0261:             * Constant for the key of the result declaration. This key can point to a
0262:             * bean declaration, which defines properties of the resulting combined
0263:             * configuration.
0264:             */
0265:            static final String KEY_RESULT = SEC_HEADER + ".result";
0266:
0267:            /** Constant for the key of the combiner in the result declaration.*/
0268:            static final String KEY_COMBINER = KEY_RESULT + ".nodeCombiner";
0269:
0270:            /** Constant for the XML file extension. */
0271:            static final String EXT_XML = ".xml";
0272:
0273:            /** Constant for the provider for properties files. */
0274:            private static final ConfigurationProvider PROPERTIES_PROVIDER = new FileExtensionConfigurationProvider(
0275:                    XMLPropertiesConfiguration.class,
0276:                    PropertiesConfiguration.class, EXT_XML);
0277:
0278:            /** Constant for the provider for XML files. */
0279:            private static final ConfigurationProvider XML_PROVIDER = new FileConfigurationProvider(
0280:                    XMLConfiguration.class);
0281:
0282:            /** Constant for the provider for JNDI sources. */
0283:            private static final ConfigurationProvider JNDI_PROVIDER = new ConfigurationProvider(
0284:                    JNDIConfiguration.class);
0285:
0286:            /** Constant for the provider for system properties. */
0287:            private static final ConfigurationProvider SYSTEM_PROVIDER = new ConfigurationProvider(
0288:                    SystemConfiguration.class);
0289:
0290:            /** Constant for the provider for plist files. */
0291:            private static final ConfigurationProvider PLIST_PROVIDER = new FileExtensionConfigurationProvider(
0292:                    "org.apache.commons.configuration.plist.XMLPropertyListConfiguration",
0293:                    "org.apache.commons.configuration.plist.PropertyListConfiguration",
0294:                    EXT_XML);
0295:
0296:            /** Constant for the provider for configuration definition files.*/
0297:            private static final ConfigurationProvider BUILDER_PROVIDER = new ConfigurationBuilderProvider();
0298:
0299:            /** An array with the names of the default tags. */
0300:            private static final String[] DEFAULT_TAGS = { "properties", "xml",
0301:                    "hierarchicalXml", "jndi", "system", "plist",
0302:                    "configuration" };
0303:
0304:            /** An array with the providers for the default tags. */
0305:            private static final ConfigurationProvider[] DEFAULT_PROVIDERS = {
0306:                    PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER,
0307:                    JNDI_PROVIDER, SYSTEM_PROVIDER, PLIST_PROVIDER,
0308:                    BUILDER_PROVIDER };
0309:
0310:            /**
0311:             * The serial version UID.
0312:             */
0313:            private static final long serialVersionUID = -3113777854714492123L;
0314:
0315:            /** Stores the configuration that is currently constructed.*/
0316:            private CombinedConfiguration constructedConfiguration;
0317:
0318:            /** Stores a map with the registered configuration providers. */
0319:            private Map providers;
0320:
0321:            /** Stores the base path to the configuration sources to load. */
0322:            private String configurationBasePath;
0323:
0324:            /**
0325:             * Creates a new instance of <code>DefaultConfigurationBuilder</code>. A
0326:             * configuration definition file is not yet loaded. Use the diverse setter
0327:             * methods provided by file based configurations to specify the
0328:             * configuration definition file.
0329:             */
0330:            public DefaultConfigurationBuilder() {
0331:                super ();
0332:                providers = new HashMap();
0333:                registerDefaultProviders();
0334:            }
0335:
0336:            /**
0337:             * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
0338:             * sets the specified configuration definition file.
0339:             *
0340:             * @param file the configuration definition file
0341:             */
0342:            public DefaultConfigurationBuilder(File file) {
0343:                this ();
0344:                setFile(file);
0345:            }
0346:
0347:            /**
0348:             * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
0349:             * sets the specified configuration definition file.
0350:             *
0351:             * @param fileName the name of the configuration definition file
0352:             * @throws ConfigurationException if an error occurs when the file is loaded
0353:             */
0354:            public DefaultConfigurationBuilder(String fileName)
0355:                    throws ConfigurationException {
0356:                this ();
0357:                setFileName(fileName);
0358:            }
0359:
0360:            /**
0361:             * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
0362:             * sets the specified configuration definition file.
0363:             *
0364:             * @param url the URL to the configuration definition file
0365:             * @throws ConfigurationException if an error occurs when the file is loaded
0366:             */
0367:            public DefaultConfigurationBuilder(URL url)
0368:                    throws ConfigurationException {
0369:                this ();
0370:                setURL(url);
0371:            }
0372:
0373:            /**
0374:             * Returns the base path for the configuration sources to load. This path is
0375:             * used to resolve relative paths in the configuration definition file.
0376:             *
0377:             * @return the base path for configuration sources
0378:             */
0379:            public String getConfigurationBasePath() {
0380:                return (configurationBasePath != null) ? configurationBasePath
0381:                        : getBasePath();
0382:            }
0383:
0384:            /**
0385:             * Sets the base path for the configuration sources to load. Normally a base
0386:             * path need not to be set because it is determined by the location of the
0387:             * configuration definition file to load. All relative pathes in this file
0388:             * are resolved relative to this file. Setting a base path makes sense if
0389:             * such relative pathes should be otherwise resolved, e.g. if the
0390:             * configuration file is loaded from the class path and all sub
0391:             * configurations it refers to are stored in a special config directory.
0392:             *
0393:             * @param configurationBasePath the new base path to set
0394:             */
0395:            public void setConfigurationBasePath(String configurationBasePath) {
0396:                this .configurationBasePath = configurationBasePath;
0397:            }
0398:
0399:            /**
0400:             * Adds a configuration provider for the specified tag. Whenever this tag is
0401:             * encountered in the configuration definition file this provider will be
0402:             * called to create the configuration object.
0403:             *
0404:             * @param tagName the name of the tag in the configuration definition file
0405:             * @param provider the provider for this tag
0406:             */
0407:            public void addConfigurationProvider(String tagName,
0408:                    ConfigurationProvider provider) {
0409:                if (tagName == null) {
0410:                    throw new IllegalArgumentException(
0411:                            "Tag name must not be null!");
0412:                }
0413:                if (provider == null) {
0414:                    throw new IllegalArgumentException(
0415:                            "Provider must not be null!");
0416:                }
0417:
0418:                providers.put(tagName, provider);
0419:            }
0420:
0421:            /**
0422:             * Removes the configuration provider for the specified tag name.
0423:             *
0424:             * @param tagName the tag name
0425:             * @return the removed configuration provider or <b>null</b> if none was
0426:             * registered for that tag
0427:             */
0428:            public ConfigurationProvider removeConfigurationProvider(
0429:                    String tagName) {
0430:                return (ConfigurationProvider) providers.remove(tagName);
0431:            }
0432:
0433:            /**
0434:             * Returns the configuration provider for the given tag.
0435:             *
0436:             * @param tagName the name of the tag
0437:             * @return the provider that was registered for this tag or <b>null</b> if
0438:             * there is none
0439:             */
0440:            public ConfigurationProvider providerForTag(String tagName) {
0441:                return (ConfigurationProvider) providers.get(tagName);
0442:            }
0443:
0444:            /**
0445:             * Returns the configuration provided by this builder. Loads and parses the
0446:             * configuration definition file and creates instances for the declared
0447:             * configurations.
0448:             *
0449:             * @return the configuration
0450:             * @throws ConfigurationException if an error occurs
0451:             */
0452:            public Configuration getConfiguration()
0453:                    throws ConfigurationException {
0454:                return getConfiguration(true);
0455:            }
0456:
0457:            /**
0458:             * Returns the configuration provided by this builder. If the boolean
0459:             * parameter is <b>true</b>, the configuration definition file will be
0460:             * loaded. It will then be parsed, and instances for the declared
0461:             * configurations will be created.
0462:             *
0463:             * @param load a flag whether the configuration definition file should be
0464:             * loaded; a value of <b>false</b> would make sense if the file has already
0465:             * been created or its content was manipulated using some of the property
0466:             * accessor methods
0467:             * @return the configuration
0468:             * @throws ConfigurationException if an error occurs
0469:             */
0470:            public CombinedConfiguration getConfiguration(boolean load)
0471:                    throws ConfigurationException {
0472:                if (load) {
0473:                    load();
0474:                }
0475:
0476:                CombinedConfiguration result = createResultConfiguration();
0477:                constructedConfiguration = result;
0478:
0479:                List overrides = fetchTopLevelOverrideConfigs();
0480:                overrides.addAll(fetchChildConfigs(KEY_OVERRIDE));
0481:                initCombinedConfiguration(result, overrides, KEY_OVERRIDE_LIST);
0482:
0483:                List additionals = fetchChildConfigs(KEY_UNION);
0484:                if (!additionals.isEmpty()) {
0485:                    CombinedConfiguration addConfig = new CombinedConfiguration(
0486:                            new UnionCombiner());
0487:                    result.addConfiguration(addConfig, ADDITIONAL_NAME);
0488:                    initCombinedConfiguration(addConfig, additionals,
0489:                            KEY_ADDITIONAL_LIST);
0490:                }
0491:
0492:                return result;
0493:            }
0494:
0495:            /**
0496:             * Creates the resulting combined configuration. This method is called by
0497:             * <code>getConfiguration()</code>. It checks whether the
0498:             * <code>header</code> section of the configuration definition file
0499:             * contains a <code>result</code> element. If this is the case, it will be
0500:             * used to initialize the properties of the newly created configuration
0501:             * object.
0502:             *
0503:             * @return the resulting configuration object
0504:             * @throws ConfigurationException if an error occurs
0505:             */
0506:            protected CombinedConfiguration createResultConfiguration()
0507:                    throws ConfigurationException {
0508:                XMLBeanDeclaration decl = new XMLBeanDeclaration(this ,
0509:                        KEY_RESULT, true);
0510:                CombinedConfiguration result = (CombinedConfiguration) BeanHelper
0511:                        .createBean(decl, CombinedConfiguration.class);
0512:
0513:                if (getMaxIndex(KEY_COMBINER) < 0) {
0514:                    // No combiner defined => set default
0515:                    result.setNodeCombiner(new OverrideCombiner());
0516:                }
0517:
0518:                return result;
0519:            }
0520:
0521:            /**
0522:             * Initializes a combined configuration for the configurations of a specific
0523:             * section. This method is called for the override and for the additional
0524:             * section (if it exists).
0525:             *
0526:             * @param config the configuration to be initialized
0527:             * @param containedConfigs the list with the declaratinos of the contained
0528:             * configurations
0529:             * @param keyListNodes a list with the declaration of list nodes
0530:             * @throws ConfigurationException if an error occurs
0531:             */
0532:            protected void initCombinedConfiguration(
0533:                    CombinedConfiguration config, List containedConfigs,
0534:                    String keyListNodes) throws ConfigurationException {
0535:                List listNodes = getList(keyListNodes);
0536:                for (Iterator it = listNodes.iterator(); it.hasNext();) {
0537:                    config.getNodeCombiner().addListNode((String) it.next());
0538:                }
0539:
0540:                for (Iterator it = containedConfigs.iterator(); it.hasNext();) {
0541:                    HierarchicalConfiguration conf = (HierarchicalConfiguration) it
0542:                            .next();
0543:                    ConfigurationDeclaration decl = new ConfigurationDeclaration(
0544:                            this , conf);
0545:                    AbstractConfiguration newConf = createConfigurationAt(decl);
0546:                    if (newConf != null) {
0547:                        config.addConfiguration(newConf, decl
0548:                                .getConfiguration().getString(ATTR_NAME), decl
0549:                                .getAt());
0550:                    }
0551:                }
0552:            }
0553:
0554:            /**
0555:             * Registers the default configuration providers supported by this class.
0556:             * This method will be called during initialization. It registers
0557:             * configuration providers for the tags that are supported by default.
0558:             */
0559:            protected void registerDefaultProviders() {
0560:                for (int i = 0; i < DEFAULT_TAGS.length; i++) {
0561:                    addConfigurationProvider(DEFAULT_TAGS[i],
0562:                            DEFAULT_PROVIDERS[i]);
0563:                }
0564:            }
0565:
0566:            /**
0567:             * Performs interpolation. This method will not only take this configuration
0568:             * instance into account (which is the one that loaded the configuration
0569:             * definition file), but also the so far constructed combined configuration.
0570:             * So variables can be used that point to properties that are defined in
0571:             * configuration sources loaded by this builder.
0572:             *
0573:             * @param value the value to be interpolated
0574:             * @return the interpolated value
0575:             */
0576:            protected Object interpolate(Object value) {
0577:                Object result = super .interpolate(value);
0578:                if (constructedConfiguration != null) {
0579:                    result = constructedConfiguration.interpolate(result);
0580:                }
0581:                return result;
0582:            }
0583:
0584:            /**
0585:             * Creates a configuration object from the specified configuration
0586:             * declaration.
0587:             *
0588:             * @param decl the configuration declaration
0589:             * @return the new configuration object
0590:             * @throws ConfigurationException if an error occurs
0591:             */
0592:            private AbstractConfiguration createConfigurationAt(
0593:                    ConfigurationDeclaration decl)
0594:                    throws ConfigurationException {
0595:                try {
0596:                    return (AbstractConfiguration) BeanHelper.createBean(decl);
0597:                } catch (Exception ex) {
0598:                    // redirect to configuration exceptions
0599:                    throw new ConfigurationException(ex);
0600:                }
0601:            }
0602:
0603:            /**
0604:             * Returns a list with <code>SubnodeConfiguration</code> objects for the
0605:             * child nodes of the specified configuration node.
0606:             *
0607:             * @param node the start node
0608:             * @return a list with subnode configurations for the node's children
0609:             */
0610:            private List fetchChildConfigs(ConfigurationNode node) {
0611:                List children = node.getChildren();
0612:                List result = new ArrayList(children.size());
0613:                for (Iterator it = children.iterator(); it.hasNext();) {
0614:                    result.add(createSubnodeConfiguration((Node) it.next()));
0615:                }
0616:                return result;
0617:            }
0618:
0619:            /**
0620:             * Returns a list with <code>SubnodeConfiguration</code> objects for the
0621:             * child nodes of the node specified by the given key.
0622:             *
0623:             * @param key the key (must define exactly one node)
0624:             * @return a list with subnode configurations for the node's children
0625:             */
0626:            private List fetchChildConfigs(String key) {
0627:                List nodes = fetchNodeList(key);
0628:                if (nodes.size() > 0) {
0629:                    return fetchChildConfigs((ConfigurationNode) nodes.get(0));
0630:                } else {
0631:                    return Collections.EMPTY_LIST;
0632:                }
0633:            }
0634:
0635:            /**
0636:             * Finds the override configurations that are defined as top level elements
0637:             * in the configuration definition file. This method will fetch the child
0638:             * elements of the root node and remove the nodes that represent other
0639:             * configuration sections. The remaining nodes are treated as definitions
0640:             * for override configurations.
0641:             *
0642:             * @return a list with subnode configurations for the top level override
0643:             * configurations
0644:             */
0645:            private List fetchTopLevelOverrideConfigs() {
0646:                List configs = fetchChildConfigs(getRootNode());
0647:                for (Iterator it = configs.iterator(); it.hasNext();) {
0648:                    String nodeName = ((SubnodeConfiguration) it.next())
0649:                            .getRootNode().getName();
0650:                    for (int i = 0; i < CONFIG_SECTIONS.length; i++) {
0651:                        if (CONFIG_SECTIONS[i].equals(nodeName)) {
0652:                            it.remove();
0653:                            break;
0654:                        }
0655:                    }
0656:                }
0657:                return configs;
0658:            }
0659:
0660:            /**
0661:             * <p>
0662:             * A base class for creating and initializing configuration sources.
0663:             * </p>
0664:             * <p>
0665:             * Concrete sub classes of this base class are responsible for creating
0666:             * specific <code>Configuration</code> objects for the tags in the
0667:             * configuration definition file. The configuration factory will parse the
0668:             * definition file and try to find a matching
0669:             * <code>ConfigurationProvider</code> for each encountered tag. This
0670:             * provider is then asked to create a corresponding
0671:             * <code>Configuration</code> object. It is up to a concrete
0672:             * implementation how this object is created and initialized.
0673:             * </p>
0674:             * <p>
0675:             * Note that at the moment only configuration classes derived from
0676:             * <code>{@link AbstractConfiguration}</code> are supported.
0677:             * </p>
0678:             */
0679:            public static class ConfigurationProvider extends
0680:                    DefaultBeanFactory {
0681:                /** Stores the class of the configuration to be created. */
0682:                private Class configurationClass;
0683:
0684:                /** Stores the name of the configuration class to be created.*/
0685:                private String configurationClassName;
0686:
0687:                /**
0688:                 * Creates a new uninitialized instance of
0689:                 * <code>ConfigurationProvider</code>.
0690:                 */
0691:                public ConfigurationProvider() {
0692:                    this ((Class) null);
0693:                }
0694:
0695:                /**
0696:                 * Creates a new instance of <code>ConfigurationProvider</code> and
0697:                 * sets the class of the configuration created by this provider.
0698:                 *
0699:                 * @param configClass the configuration class
0700:                 */
0701:                public ConfigurationProvider(Class configClass) {
0702:                    setConfigurationClass(configClass);
0703:                }
0704:
0705:                /**
0706:                 * Creates a new instance of <code>ConfigurationProvider</code> and
0707:                 * sets the name of the class of the configuration created by this
0708:                 * provider.
0709:                 *
0710:                 * @param configClassName the name of the configuration class
0711:                 * @since 1.4
0712:                 */
0713:                public ConfigurationProvider(String configClassName) {
0714:                    setConfigurationClassName(configClassName);
0715:                }
0716:
0717:                /**
0718:                 * Returns the class of the configuration returned by this provider.
0719:                 *
0720:                 * @return the class of the provided configuration
0721:                 */
0722:                public Class getConfigurationClass() {
0723:                    return configurationClass;
0724:                }
0725:
0726:                /**
0727:                 * Sets the class of the configuration returned by this provider.
0728:                 *
0729:                 * @param configurationClass the configuration class
0730:                 */
0731:                public void setConfigurationClass(Class configurationClass) {
0732:                    this .configurationClass = configurationClass;
0733:                }
0734:
0735:                /**
0736:                 * Returns the name of the configuration class returned by this
0737:                 * provider.
0738:                 *
0739:                 * @return the configuration class name
0740:                 * @since 1.4
0741:                 */
0742:                public String getConfigurationClassName() {
0743:                    return configurationClassName;
0744:                }
0745:
0746:                /**
0747:                 * Sets the name of the configuration class returned by this provider.
0748:                 *
0749:                 * @param configurationClassName the name of the configuration class
0750:                 * @since 1.4
0751:                 */
0752:                public void setConfigurationClassName(
0753:                        String configurationClassName) {
0754:                    this .configurationClassName = configurationClassName;
0755:                }
0756:
0757:                /**
0758:                 * Returns the configuration. This method is called to fetch the
0759:                 * configuration from the provider. This implementation will call the
0760:                 * inherited <code>{@link
0761:                 * org.apache.commons.configuration.beanutils.DefaultBeanFactory#createBean(Class, BeanDeclaration, Object)
0762:                 * createBean()}</code> method to create a new instance of the
0763:                 * configuration class.
0764:                 *
0765:                 * @param decl the bean declaration with initialization parameters for
0766:                 * the configuration
0767:                 * @return the new configuration object
0768:                 * @throws Exception if an error occurs
0769:                 */
0770:                public AbstractConfiguration getConfiguration(
0771:                        ConfigurationDeclaration decl) throws Exception {
0772:                    return (AbstractConfiguration) createBean(
0773:                            fetchConfigurationClass(), decl, null);
0774:                }
0775:
0776:                /**
0777:                 * Returns an uninitialized configuration of the represented type. This
0778:                 * method will be called for optional configurations when the
0779:                 * <code>getConfiguration()</code> method caused an error and the
0780:                 * <code>forceCreate</code> attribute is set. A concrete sub class can
0781:                 * here try to create an uninitialized, empty configuration, which may
0782:                 * be possible if the error was created during initialization. This base
0783:                 * implementation just returns <b>null</b>.
0784:                 *
0785:                 * @param decl the bean declaration with initialization parameters for
0786:                 * the configuration
0787:                 * @return the new configuration object
0788:                 * @throws Exception if an error occurs
0789:                 * @since 1.4
0790:                 */
0791:                public AbstractConfiguration getEmptyConfiguration(
0792:                        ConfigurationDeclaration decl) throws Exception {
0793:                    return null;
0794:                }
0795:
0796:                /**
0797:                 * Returns the configuration class supported by this provider. If a
0798:                 * class object was set, it is returned. Otherwise the method tries to
0799:                 * resolve the class name.
0800:                 *
0801:                 * @return the class of the configuration to be created
0802:                 * @since 1.4
0803:                 */
0804:                protected synchronized Class fetchConfigurationClass()
0805:                        throws Exception {
0806:                    if (getConfigurationClass() == null) {
0807:                        setConfigurationClass(loadClass(getConfigurationClassName()));
0808:                    }
0809:                    return getConfigurationClass();
0810:                }
0811:
0812:                /**
0813:                 * Loads the class with the specified name dynamically. If the class's
0814:                 * name is <b>null</b>, <b>null</b> will also be returned.
0815:                 *
0816:                 * @param className the name of the class to be loaded
0817:                 * @return the class object
0818:                 * @throws ClassNotFoundException if class loading fails
0819:                 * @since 1.4
0820:                 */
0821:                protected Class loadClass(String className)
0822:                        throws ClassNotFoundException {
0823:                    return (className != null) ? Class.forName(className, true,
0824:                            getClass().getClassLoader()) : null;
0825:                }
0826:            }
0827:
0828:            /**
0829:             * <p>
0830:             * A specialized <code>BeanDeclaration</code> implementation that
0831:             * represents the declaration of a configuration source.
0832:             * </p>
0833:             * <p>
0834:             * Instances of this class are able to extract all information about a
0835:             * configuration source from the configuration definition file. The
0836:             * declaration of a configuration source is very similar to a bean
0837:             * declaration processed by <code>XMLBeanDeclaration</code>. There are
0838:             * very few differences, e.g. some reserved attributes like
0839:             * <code>optional</code> and <code>at</code> and the fact that a bean
0840:             * factory is never needed.
0841:             * </p>
0842:             */
0843:            public static class ConfigurationDeclaration extends
0844:                    XMLBeanDeclaration {
0845:                /** Stores a reference to the associated configuration builder. */
0846:                private DefaultConfigurationBuilder configurationBuilder;
0847:
0848:                /**
0849:                 * Creates a new instance of <code>ConfigurationDeclaration</code> and
0850:                 * initializes it.
0851:                 *
0852:                 * @param builder the associated configuration builder
0853:                 * @param config the configuration this declaration is based onto
0854:                 */
0855:                public ConfigurationDeclaration(
0856:                        DefaultConfigurationBuilder builder,
0857:                        HierarchicalConfiguration config) {
0858:                    super (config);
0859:                    configurationBuilder = builder;
0860:                }
0861:
0862:                /**
0863:                 * Returns the associated configuration builder.
0864:                 *
0865:                 * @return the configuration builder
0866:                 */
0867:                public DefaultConfigurationBuilder getConfigurationBuilder() {
0868:                    return configurationBuilder;
0869:                }
0870:
0871:                /**
0872:                 * Returns the value of the <code>at</code> attribute.
0873:                 *
0874:                 * @return the value of the <code>at</code> attribute (can be <b>null</b>)
0875:                 */
0876:                public String getAt() {
0877:                    String result = this .getConfiguration().getString(
0878:                            ATTR_AT_RES);
0879:                    return (result == null) ? this .getConfiguration()
0880:                            .getString(ATTR_AT) : result;
0881:                }
0882:
0883:                /**
0884:                 * Returns a flag whether this is an optional configuration.
0885:                 *
0886:                 * @return a flag if this declaration points to an optional
0887:                 * configuration
0888:                 */
0889:                public boolean isOptional() {
0890:                    Boolean value = this .getConfiguration().getBoolean(
0891:                            ATTR_OPTIONAL_RES, null);
0892:                    if (value == null) {
0893:                        value = this .getConfiguration().getBoolean(
0894:                                ATTR_OPTIONAL, Boolean.FALSE);
0895:                    }
0896:                    return value.booleanValue();
0897:                }
0898:
0899:                /**
0900:                 * Returns a flag whether this configuration should always be created
0901:                 * and added to the resulting combined configuration. This flag is
0902:                 * evaluated only for optional configurations whose normal creation has
0903:                 * caused an error. If for such a configuration the
0904:                 * <code>forceCreate</code> attribute is set and the corresponding
0905:                 * configuration provider supports this mode, an empty configuration
0906:                 * will be created and added to the resulting combined configuration.
0907:                 *
0908:                 * @return the value of the <code>forceCreate</code> attribute
0909:                 * @since 1.4
0910:                 */
0911:                public boolean isForceCreate() {
0912:                    return this .getConfiguration().getBoolean(ATTR_FORCECREATE,
0913:                            false);
0914:                }
0915:
0916:                /**
0917:                 * Returns the name of the bean factory. For configuration source
0918:                 * declarations always a reserved factory is used. This factory's name
0919:                 * is returned by this implementation.
0920:                 *
0921:                 * @return the name of the bean factory
0922:                 */
0923:                public String getBeanFactoryName() {
0924:                    return CONFIG_BEAN_FACTORY_NAME;
0925:                }
0926:
0927:                /**
0928:                 * Returns the bean's class name. This implementation will always return
0929:                 * <b>null</b>.
0930:                 *
0931:                 * @return the name of the bean's class
0932:                 */
0933:                public String getBeanClassName() {
0934:                    return null;
0935:                }
0936:
0937:                /**
0938:                 * Checks whether the given node is reserved. This method will take
0939:                 * further reserved attributes into account
0940:                 *
0941:                 * @param nd the node
0942:                 * @return a flag whether this node is reserved
0943:                 */
0944:                protected boolean isReservedNode(ConfigurationNode nd) {
0945:                    if (super .isReservedNode(nd)) {
0946:                        return true;
0947:                    }
0948:
0949:                    return nd.isAttribute()
0950:                            && ((ATTR_ATNAME.equals(nd.getName()) && nd
0951:                                    .getParentNode().getAttributeCount(
0952:                                            RESERVED_PREFIX + ATTR_ATNAME) == 0) || (ATTR_OPTIONALNAME
0953:                                    .equals(nd.getName()) && nd
0954:                                    .getParentNode()
0955:                                    .getAttributeCount(
0956:                                            RESERVED_PREFIX + ATTR_OPTIONALNAME) == 0));
0957:                }
0958:
0959:                /**
0960:                 * Performs interpolation. This implementation will delegate
0961:                 * interpolation to the configuration builder, which takes care that the
0962:                 * currently constructed configuration is taken into account, too.
0963:                 *
0964:                 * @param value the value to be interpolated
0965:                 * @return the interpolated value
0966:                 */
0967:                protected Object interpolate(Object value) {
0968:                    return getConfigurationBuilder().interpolate(value);
0969:                }
0970:            }
0971:
0972:            /**
0973:             * A specialized <code>BeanFactory</code> implementation that handles
0974:             * configuration declarations. This class will retrieve the correct
0975:             * configuration provider and delegate the task of creating the
0976:             * configuration to this object.
0977:             */
0978:            static class ConfigurationBeanFactory implements  BeanFactory {
0979:                /**
0980:                 * Creates an instance of a bean class. This implementation expects that
0981:                 * the passed in bean declaration is a declaration for a configuration.
0982:                 * It will determine the responsible configuration provider and delegate
0983:                 * the call to this instance. If creation of the configuration fails
0984:                 * and the <code>optional</code> attribute is set, the exception will
0985:                 * be ignored. If the <code>forceCreate</code> attribute is set, too,
0986:                 * the provider is asked to create an empty configuration. A return
0987:                 * value of <b>null</b> means that no configuration could be created.
0988:                 *
0989:                 * @param beanClass the bean class (will be ignored)
0990:                 * @param data the declaration
0991:                 * @param param an additional parameter (will be ignored)
0992:                 * @return the newly created configuration
0993:                 * @throws Exception if an error occurs
0994:                 */
0995:                public Object createBean(Class beanClass, BeanDeclaration data,
0996:                        Object param) throws Exception {
0997:                    ConfigurationDeclaration decl = (ConfigurationDeclaration) data;
0998:                    String tagName = decl.getNode().getName();
0999:                    ConfigurationProvider provider = decl
1000:                            .getConfigurationBuilder().providerForTag(tagName);
1001:                    if (provider == null) {
1002:                        throw new ConfigurationRuntimeException(
1003:                                "No ConfigurationProvider registered for tag "
1004:                                        + tagName);
1005:                    }
1006:
1007:                    try {
1008:                        return provider.getConfiguration(decl);
1009:                    } catch (Exception ex) {
1010:                        // If this is an optional configuration, ignore the exception
1011:                        if (!decl.isOptional()) {
1012:                            throw ex;
1013:                        } else {
1014:                            if (decl.isForceCreate()) {
1015:                                try {
1016:                                    return provider.getEmptyConfiguration(decl);
1017:                                } catch (Exception ex2) {
1018:                                    // Ignore exception, return null in this case
1019:                                    ;
1020:                                }
1021:                            }
1022:                            return null;
1023:                        }
1024:                    }
1025:                }
1026:
1027:                /**
1028:                 * Returns the default class for this bean factory.
1029:                 *
1030:                 * @return the default class
1031:                 */
1032:                public Class getDefaultBeanClass() {
1033:                    // Here some valid class must be returned, otherwise BeanHelper
1034:                    // will complain that the bean's class cannot be determined
1035:                    return Configuration.class;
1036:                }
1037:            }
1038:
1039:            /**
1040:             * A specialized provider implementation that deals with file based
1041:             * configurations. Ensures that the base path is correctly set and that the
1042:             * load() method gets called.
1043:             */
1044:            public static class FileConfigurationProvider extends
1045:                    ConfigurationProvider {
1046:                /**
1047:                 * Creates a new instance of <code>FileConfigurationProvider</code>.
1048:                 */
1049:                public FileConfigurationProvider() {
1050:                    super ();
1051:                }
1052:
1053:                /**
1054:                 * Creates a new instance of <code>FileConfigurationProvider</code>
1055:                 * and sets the configuration class.
1056:                 *
1057:                 * @param configClass the class for the configurations to be created
1058:                 */
1059:                public FileConfigurationProvider(Class configClass) {
1060:                    super (configClass);
1061:                }
1062:
1063:                /**
1064:                 * Creates a new instance of <code>FileConfigurationProvider</code>
1065:                 * and sets the configuration class name.
1066:                 *
1067:                 * @param configClassName the name of the configuration to be created
1068:                 * @since 1.4
1069:                 */
1070:                public FileConfigurationProvider(String configClassName) {
1071:                    super (configClassName);
1072:                }
1073:
1074:                /**
1075:                 * Creates the configuration. After that <code>load()</code> will be
1076:                 * called. If this configuration is marked as optional, exceptions will
1077:                 * be ignored.
1078:                 *
1079:                 * @param decl the declaration
1080:                 * @return the new configuration
1081:                 * @throws Exception if an error occurs
1082:                 */
1083:                public AbstractConfiguration getConfiguration(
1084:                        ConfigurationDeclaration decl) throws Exception {
1085:                    AbstractConfiguration result = getEmptyConfiguration(decl);
1086:                    ((FileConfiguration) result).load();
1087:                    return result;
1088:                }
1089:
1090:                /**
1091:                 * Returns an uninitialized file configuration. This method will be
1092:                 * called for optional configurations when the
1093:                 * <code>getConfiguration()</code> method caused an error and the
1094:                 * <code>forceCreate</code> attribute is set. It will create the
1095:                 * configuration of the represented type, but the <code>load()</code>
1096:                 * method won't be called. This way non-existing configuration files can
1097:                 * be handled gracefully: If loading a the file fails, an empty
1098:                 * configuration will be created that is already configured with the
1099:                 * correct file name.
1100:                 *
1101:                 * @param decl the bean declaration with initialization parameters for
1102:                 * the configuration
1103:                 * @return the new configuration object
1104:                 * @throws Exception if an error occurs
1105:                 * @since 1.4
1106:                 */
1107:                public AbstractConfiguration getEmptyConfiguration(
1108:                        ConfigurationDeclaration decl) throws Exception {
1109:                    return super .getConfiguration(decl);
1110:                }
1111:
1112:                /**
1113:                 * Initializes the bean instance. Ensures that the file configuration's
1114:                 * base path will be initialized with the base path of the factory so
1115:                 * that relative path names can be correctly resolved.
1116:                 *
1117:                 * @param bean the bean to be initialized
1118:                 * @param data the declaration
1119:                 * @throws Exception if an error occurs
1120:                 */
1121:                protected void initBeanInstance(Object bean,
1122:                        BeanDeclaration data) throws Exception {
1123:                    FileConfiguration config = (FileConfiguration) bean;
1124:                    config.setBasePath(((ConfigurationDeclaration) data)
1125:                            .getConfigurationBuilder()
1126:                            .getConfigurationBasePath());
1127:                    super .initBeanInstance(bean, data);
1128:                }
1129:            }
1130:
1131:            /**
1132:             * A specialized configuration provider for file based configurations that
1133:             * can handle configuration sources whose concrete type depends on the
1134:             * extension of the file to be loaded. One example is the
1135:             * <code>properties</code> tag: if the file ends with ".xml" a
1136:             * XMLPropertiesConfiguration object must be created, otherwise a
1137:             * PropertiesConfiguration object.
1138:             */
1139:            static class FileExtensionConfigurationProvider extends
1140:                    FileConfigurationProvider {
1141:                /**
1142:                 * Stores the class to be created when the file extension matches.
1143:                 */
1144:                private Class matchingClass;
1145:
1146:                /**
1147:                 * Stores the name of the class to be created when the file extension
1148:                 * matches.
1149:                 */
1150:                private String matchingClassName;
1151:
1152:                /**
1153:                 * Stores the class to be created when the file extension does not
1154:                 * match.
1155:                 */
1156:                private Class defaultClass;
1157:
1158:                /**
1159:                 * Stores the name of the class to be created when the file extension
1160:                 * does not match.
1161:                 */
1162:                private String defaultClassName;
1163:
1164:                /** Stores the file extension to be checked against. */
1165:                private String fileExtension;
1166:
1167:                /**
1168:                 * Creates a new instance of
1169:                 * <code>FileExtensionConfigurationProvider</code> and initializes it.
1170:                 *
1171:                 * @param matchingClass the class to be created when the file extension
1172:                 * matches
1173:                 * @param defaultClass the class to be created when the file extension
1174:                 * does not match
1175:                 * @param extension the file extension to be checked agains
1176:                 */
1177:                public FileExtensionConfigurationProvider(Class matchingClass,
1178:                        Class defaultClass, String extension) {
1179:                    this .matchingClass = matchingClass;
1180:                    this .defaultClass = defaultClass;
1181:                    fileExtension = extension;
1182:                }
1183:
1184:                /**
1185:                 * Creates a new instance of
1186:                 * <code>FileExtensionConfigurationProvider</code> and initializes it
1187:                 * with the names of the classes to be created.
1188:                 *
1189:                 * @param matchingClassName the name of the class to be created when the
1190:                 * file extension matches
1191:                 * @param defaultClassName the name of the class to be created when the
1192:                 * file extension does not match
1193:                 * @param extension the file extension to be checked agains
1194:                 * @since 1.4
1195:                 */
1196:                public FileExtensionConfigurationProvider(
1197:                        String matchingClassName, String defaultClassName,
1198:                        String extension) {
1199:                    this .matchingClassName = matchingClassName;
1200:                    this .defaultClassName = defaultClassName;
1201:                    fileExtension = extension;
1202:                }
1203:
1204:                /**
1205:                 * Returns the matching class object, no matter whether it was defined
1206:                 * as a class or as a class name.
1207:                 *
1208:                 * @return the matching class object
1209:                 * @throws Exception if an error occurs
1210:                 * @since 1.4
1211:                 */
1212:                protected synchronized Class fetchMatchingClass()
1213:                        throws Exception {
1214:                    if (matchingClass == null) {
1215:                        matchingClass = loadClass(matchingClassName);
1216:                    }
1217:                    return matchingClass;
1218:                }
1219:
1220:                /**
1221:                 * Returns the default class object, no matter whether it was defined as
1222:                 * a class or as a class name.
1223:                 *
1224:                 * @return the default class object
1225:                 * @throws Exception if an error occurs
1226:                 * @since 1.4
1227:                 */
1228:                protected synchronized Class fetchDefaultClass()
1229:                        throws Exception {
1230:                    if (defaultClass == null) {
1231:                        defaultClass = loadClass(defaultClassName);
1232:                    }
1233:                    return defaultClass;
1234:                }
1235:
1236:                /**
1237:                 * Creates the configuration object. The class is determined by the file
1238:                 * name's extension.
1239:                 *
1240:                 * @param beanClass the class
1241:                 * @param data the bean declaration
1242:                 * @return the new bean
1243:                 * @throws Exception if an error occurs
1244:                 */
1245:                protected Object createBeanInstance(Class beanClass,
1246:                        BeanDeclaration data) throws Exception {
1247:                    String fileName = ((ConfigurationDeclaration) data)
1248:                            .getConfiguration().getString(ATTR_FILENAME);
1249:                    if (fileName != null
1250:                            && fileName.toLowerCase().trim().endsWith(
1251:                                    fileExtension)) {
1252:                        return super .createBeanInstance(fetchMatchingClass(),
1253:                                data);
1254:                    } else {
1255:                        return super .createBeanInstance(fetchDefaultClass(),
1256:                                data);
1257:                    }
1258:                }
1259:            }
1260:
1261:            /**
1262:             * A specialized configuration provider class that allows to include other
1263:             * configuration definition files.
1264:             */
1265:            static class ConfigurationBuilderProvider extends
1266:                    ConfigurationProvider {
1267:                /**
1268:                 * Creates a new instance of <code>ConfigurationBuilderProvider</code>.
1269:                 */
1270:                public ConfigurationBuilderProvider() {
1271:                    super (DefaultConfigurationBuilder.class);
1272:                }
1273:
1274:                /**
1275:                 * Creates the configuration. First creates a configuration builder
1276:                 * object. Then returns the configuration created by this builder.
1277:                 *
1278:                 * @param decl the configuration declaration
1279:                 * @return the configuration
1280:                 * @exception Exception if an error occurs
1281:                 */
1282:                public AbstractConfiguration getConfiguration(
1283:                        ConfigurationDeclaration decl) throws Exception {
1284:                    DefaultConfigurationBuilder builder = (DefaultConfigurationBuilder) super 
1285:                            .getConfiguration(decl);
1286:                    return builder.getConfiguration(true);
1287:                }
1288:
1289:                /**
1290:                 * Returns an empty configuration in case of an optional configuration
1291:                 * could not be created. This implementation returns an empty combined
1292:                 * configuration.
1293:                 *
1294:                 * @param decl the configuration declaration
1295:                 * @return the configuration
1296:                 * @exception Exception if an error occurs
1297:                 * @since 1.4
1298:                 */
1299:                public AbstractConfiguration getEmptyConfiguration(
1300:                        ConfigurationDeclaration decl) throws Exception {
1301:                    return new CombinedConfiguration();
1302:                }
1303:            }
1304:
1305:            static {
1306:                // register the configuration bean factory
1307:                BeanHelper.registerBeanFactory(CONFIG_BEAN_FACTORY_NAME,
1308:                        new ConfigurationBeanFactory());
1309:            }
1310:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.