Source Code Cross Referenced for ConfigurationFactory.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) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:
018:        package org.apache.commons.configuration;
019:
020:        import java.io.File;
021:        import java.io.IOException;
022:        import java.io.InputStream;
023:        import java.net.URL;
024:        import java.util.Collection;
025:        import java.util.Iterator;
026:        import java.util.LinkedList;
027:        import java.util.Map;
028:
029:        import org.apache.commons.configuration.plist.PropertyListConfiguration;
030:        import org.apache.commons.configuration.plist.XMLPropertyListConfiguration;
031:        import org.apache.commons.digester.AbstractObjectCreationFactory;
032:        import org.apache.commons.digester.CallMethodRule;
033:        import org.apache.commons.digester.Digester;
034:        import org.apache.commons.digester.ObjectCreationFactory;
035:        import org.apache.commons.digester.Substitutor;
036:        import org.apache.commons.digester.substitution.MultiVariableExpander;
037:        import org.apache.commons.digester.substitution.VariableSubstitutor;
038:        import org.apache.commons.digester.xmlrules.DigesterLoader;
039:        import org.apache.commons.lang.StringUtils;
040:        import org.apache.commons.logging.Log;
041:        import org.apache.commons.logging.LogFactory;
042:        import org.xml.sax.Attributes;
043:        import org.xml.sax.SAXException;
044:
045:        /**
046:         * <p>
047:         * Factory class to create a CompositeConfiguration from a .xml file using
048:         * Digester.  By default it can handle the Configurations from commons-
049:         * configuration.  If you need to add your own, then you can pass in your own
050:         * digester rules to use.  It is also namespace aware, by providing a
051:         * digesterRuleNamespaceURI.
052:         * </p>
053:         * <p>
054:         * <em>Note:</em> Almost all of the features provided by this class and many
055:         * more are also available for the <code>{@link DefaultConfigurationBuilder}</code>
056:         * class. <code>DefaultConfigurationBuilder</code> also has a more robust
057:         * merge algorithm for constructing combined configurations. So it is
058:         * recommended to use this class instead of <code>ConfigurationFactory</code>.
059:         * </p>
060:         *
061:         * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
062:         * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
063:         * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
064:         * @version $Id: ConfigurationFactory.java 524006 2007-03-30 09:33:17Z oheger $
065:         */
066:        public class ConfigurationFactory {
067:            /** Constant for the root element in the info file.*/
068:            private static final String SEC_ROOT = "configuration/";
069:
070:            /** Constant for the override section.*/
071:            private static final String SEC_OVERRIDE = SEC_ROOT + "override/";
072:
073:            /** Constant for the additional section.*/
074:            private static final String SEC_ADDITIONAL = SEC_ROOT
075:                    + "additional/";
076:
077:            /** Constant for the optional attribute.*/
078:            private static final String ATTR_OPTIONAL = "optional";
079:
080:            /** Constant for the fileName attribute.*/
081:            private static final String ATTR_FILENAME = "fileName";
082:
083:            /** Constant for the load method.*/
084:            private static final String METH_LOAD = "load";
085:
086:            /** Constant for the default base path (points to actual directory).*/
087:            private static final String DEF_BASE_PATH = ".";
088:
089:            /** static logger */
090:            private static Log log = LogFactory
091:                    .getLog(ConfigurationFactory.class);
092:
093:            /** The XML file with the details about the configuration to load */
094:            private String configurationFileName;
095:
096:            /** The URL to the XML file with the details about the configuration to load. */
097:            private URL configurationURL;
098:
099:            /**
100:             * The implicit base path for included files. This path is determined by
101:             * the configuration to load and used unless no other base path was
102:             * explicitely specified.
103:             */
104:            private String implicitBasePath;
105:
106:            /** The basePath to prefix file paths for file based property files. */
107:            private String basePath;
108:
109:            /** URL for xml digester rules file */
110:            private URL digesterRules;
111:
112:            /** The digester namespace to parse */
113:            private String digesterRuleNamespaceURI;
114:
115:            /**
116:             * Constructor
117:             */
118:            public ConfigurationFactory() {
119:                setBasePath(DEF_BASE_PATH);
120:            }
121:
122:            /**
123:             * Constructor with ConfigurationFile Name passed
124:             *
125:             * @param configurationFileName The path to the configuration file
126:             */
127:            public ConfigurationFactory(String configurationFileName) {
128:                setConfigurationFileName(configurationFileName);
129:            }
130:
131:            /**
132:             * Return the configuration provided by this factory. It loads the
133:             * configuration file which is a XML description of the actual
134:             * configurations to load. It can contain various different types of
135:             * configuration, e.g. Properties, XML and JNDI.
136:             *
137:             * @return A Configuration object
138:             * @throws ConfigurationException A generic exception that we had trouble during the
139:             * loading of the configuration data.
140:             */
141:            public Configuration getConfiguration()
142:                    throws ConfigurationException {
143:                Digester digester;
144:                InputStream input = null;
145:                ConfigurationBuilder builder = new ConfigurationBuilder();
146:                URL url = getConfigurationURL();
147:                try {
148:                    if (url == null) {
149:                        url = ConfigurationUtils.locate(implicitBasePath,
150:                                getConfigurationFileName());
151:                    }
152:                    input = url.openStream();
153:                } catch (Exception e) {
154:                    log.error("Exception caught opening stream to URL", e);
155:                    throw new ConfigurationException(
156:                            "Exception caught opening stream to URL", e);
157:                }
158:
159:                if (getDigesterRules() == null) {
160:                    digester = new Digester();
161:                    configureNamespace(digester);
162:                    initDefaultDigesterRules(digester);
163:                } else {
164:                    digester = DigesterLoader
165:                            .createDigester(getDigesterRules());
166:                    // This might already be too late. As far as I can see, the namespace
167:                    // awareness must be configured before the digester rules are loaded.
168:                    configureNamespace(digester);
169:                }
170:
171:                // Configure digester to always enable the context class loader
172:                digester.setUseContextClassLoader(true);
173:                // Add a substitutor to resolve system properties
174:                enableDigesterSubstitutor(digester);
175:                // Put the composite builder object below all of the other objects.
176:                digester.push(builder);
177:                // Parse the input stream to configure our mappings
178:                try {
179:                    digester.parse(input);
180:                    input.close();
181:                } catch (SAXException saxe) {
182:                    log.error("SAX Exception caught", saxe);
183:                    throw new ConfigurationException("SAX Exception caught",
184:                            saxe);
185:                } catch (IOException ioe) {
186:                    log.error("IO Exception caught", ioe);
187:                    throw new ConfigurationException("IO Exception caught", ioe);
188:                }
189:                return builder.getConfiguration();
190:            }
191:
192:            /**
193:             * Returns the configurationFile.
194:             *
195:             * @return The name of the configuration file. Can be null.
196:             */
197:            public String getConfigurationFileName() {
198:                return configurationFileName;
199:            }
200:
201:            /**
202:             * Sets the configurationFile.
203:             *
204:             * @param configurationFileName  The name of the configurationFile to use.
205:             */
206:            public void setConfigurationFileName(String configurationFileName) {
207:                File file = new File(configurationFileName).getAbsoluteFile();
208:                this .configurationFileName = file.getName();
209:                implicitBasePath = file.getParent();
210:            }
211:
212:            /**
213:             * Returns the URL of the configuration file to be loaded.
214:             *
215:             * @return the URL of the configuration to load
216:             */
217:            public URL getConfigurationURL() {
218:                return configurationURL;
219:            }
220:
221:            /**
222:             * Sets the URL of the configuration to load. This configuration can be
223:             * either specified by a file name or by a URL.
224:             *
225:             * @param url the URL of the configuration to load
226:             */
227:            public void setConfigurationURL(URL url) {
228:                configurationURL = url;
229:                implicitBasePath = url.toString();
230:            }
231:
232:            /**
233:             * Returns the digesterRules.
234:             *
235:             * @return URL
236:             */
237:            public URL getDigesterRules() {
238:                return digesterRules;
239:            }
240:
241:            /**
242:             * Sets the digesterRules.
243:             *
244:             * @param digesterRules The digesterRules to set
245:             */
246:            public void setDigesterRules(URL digesterRules) {
247:                this .digesterRules = digesterRules;
248:            }
249:
250:            /**
251:             * Adds a substitutor to interpolate system properties
252:             *
253:             * @param digester The digester to which we add the substitutor
254:             */
255:            protected void enableDigesterSubstitutor(Digester digester) {
256:                Map systemProperties = System.getProperties();
257:                MultiVariableExpander expander = new MultiVariableExpander();
258:                expander.addSource("$", systemProperties);
259:
260:                // allow expansion in both xml attributes and element text
261:                Substitutor substitutor = new VariableSubstitutor(expander);
262:                digester.setSubstitutor(substitutor);
263:            }
264:
265:            /**
266:             * Initializes the parsing rules for the default digester
267:             *
268:             * This allows the Configuration Factory to understand the default types:
269:             * Properties, XML and JNDI. Two special sections are introduced:
270:             * <code>&lt;override&gt;</code> and <code>&lt;additional&gt;</code>.
271:             *
272:             * @param digester The digester to configure
273:             */
274:            protected void initDefaultDigesterRules(Digester digester) {
275:                initDigesterSectionRules(digester, SEC_ROOT, false);
276:                initDigesterSectionRules(digester, SEC_OVERRIDE, false);
277:                initDigesterSectionRules(digester, SEC_ADDITIONAL, true);
278:            }
279:
280:            /**
281:             * Sets up digester rules for a specified section of the configuration
282:             * info file.
283:             *
284:             * @param digester the current digester instance
285:             * @param matchString specifies the section
286:             * @param additional a flag if rules for the additional section are to be
287:             * added
288:             */
289:            protected void initDigesterSectionRules(Digester digester,
290:                    String matchString, boolean additional) {
291:                setupDigesterInstance(digester, matchString + "properties",
292:                        new PropertiesConfigurationFactory(), METH_LOAD,
293:                        additional);
294:
295:                setupDigesterInstance(digester, matchString + "plist",
296:                        new PropertyListConfigurationFactory(), METH_LOAD,
297:                        additional);
298:
299:                setupDigesterInstance(digester, matchString + "xml",
300:                        new FileConfigurationFactory(XMLConfiguration.class),
301:                        METH_LOAD, additional);
302:
303:                setupDigesterInstance(digester,
304:                        matchString + "hierarchicalXml",
305:                        new FileConfigurationFactory(XMLConfiguration.class),
306:                        METH_LOAD, additional);
307:
308:                setupDigesterInstance(digester, matchString + "jndi",
309:                        new JNDIConfigurationFactory(), null, additional);
310:
311:                setupDigesterInstance(digester, matchString + "system",
312:                        new SystemConfigurationFactory(), null, additional);
313:            }
314:
315:            /**
316:             * Sets up digester rules for a configuration to be loaded.
317:             *
318:             * @param digester the current digester
319:             * @param matchString the pattern to match with this rule
320:             * @param factory an ObjectCreationFactory instance to use for creating new
321:             * objects
322:             * @param method the name of a method to be called or <b>null</b> for none
323:             * @param additional a flag if rules for the additional section are to be
324:             * added
325:             */
326:            protected void setupDigesterInstance(Digester digester,
327:                    String matchString, ObjectCreationFactory factory,
328:                    String method, boolean additional) {
329:                if (additional) {
330:                    setupUnionRules(digester, matchString);
331:                }
332:
333:                digester.addFactoryCreate(matchString, factory);
334:                digester.addSetProperties(matchString);
335:
336:                if (method != null) {
337:                    digester.addRule(matchString, new CallOptionalMethodRule(
338:                            method));
339:                }
340:
341:                digester.addSetNext(matchString, "addConfiguration",
342:                        Configuration.class.getName());
343:            }
344:
345:            /**
346:             * Sets up rules for configurations in the additional section.
347:             *
348:             * @param digester the current digester
349:             * @param matchString the pattern to match with this rule
350:             */
351:            protected void setupUnionRules(Digester digester, String matchString) {
352:                digester.addObjectCreate(matchString,
353:                        AdditionalConfigurationData.class);
354:                digester.addSetProperties(matchString);
355:                digester.addSetNext(matchString, "addAdditionalConfig",
356:                        AdditionalConfigurationData.class.getName());
357:            }
358:
359:            /**
360:             * Returns the digesterRuleNamespaceURI.
361:             *
362:             * @return A String with the digesterRuleNamespaceURI.
363:             */
364:            public String getDigesterRuleNamespaceURI() {
365:                return digesterRuleNamespaceURI;
366:            }
367:
368:            /**
369:             * Sets the digesterRuleNamespaceURI.
370:             *
371:             * @param digesterRuleNamespaceURI The new digesterRuleNamespaceURI to use
372:             */
373:            public void setDigesterRuleNamespaceURI(
374:                    String digesterRuleNamespaceURI) {
375:                this .digesterRuleNamespaceURI = digesterRuleNamespaceURI;
376:            }
377:
378:            /**
379:             * Configure the current digester to be namespace aware and to have
380:             * a Configuration object to which all of the other configurations
381:             * should be added
382:             *
383:             * @param digester The Digester to configure
384:             */
385:            private void configureNamespace(Digester digester) {
386:                if (getDigesterRuleNamespaceURI() != null) {
387:                    digester.setNamespaceAware(true);
388:                    digester.setRuleNamespaceURI(getDigesterRuleNamespaceURI());
389:                } else {
390:                    digester.setNamespaceAware(false);
391:                }
392:                digester.setValidating(false);
393:            }
394:
395:            /**
396:             * Returns the Base path from which this Configuration Factory operates.
397:             * This is never null. If you set the BasePath to null, then a base path
398:             * according to the configuration to load is returned.
399:             *
400:             * @return The base Path of this configuration factory.
401:             */
402:            public String getBasePath() {
403:                String path = StringUtils.isEmpty(basePath)
404:                        || DEF_BASE_PATH.equals(basePath) ? implicitBasePath
405:                        : basePath;
406:                return StringUtils.isEmpty(path) ? DEF_BASE_PATH : path;
407:            }
408:
409:            /**
410:             * Sets the basePath for all file references from this Configuration Factory.
411:             * Normally a base path need not to be set because it is determined by
412:             * the location of the configuration file to load. All relative pathes in
413:             * this file are resolved relative to this file. Setting a base path makes
414:             * sense if such relative pathes should be otherwise resolved, e.g. if
415:             * the configuration file is loaded from the class path and all sub
416:             * configurations it refers to are stored in a special config directory.
417:             *
418:             * @param basePath The new basePath to set.
419:             */
420:            public void setBasePath(String basePath) {
421:                this .basePath = basePath;
422:            }
423:
424:            /**
425:             * A base class for digester factory classes. This base class maintains
426:             * a default class for the objects to be created.
427:             * There will be sub classes for specific configuration implementations.
428:             */
429:            public class DigesterConfigurationFactory extends
430:                    AbstractObjectCreationFactory {
431:                /** Actual class to use. */
432:                private Class clazz;
433:
434:                /**
435:                 * Creates a new instance of <code>DigesterConfigurationFactory</code>.
436:                 *
437:                 * @param clazz the class which we should instantiate
438:                 */
439:                public DigesterConfigurationFactory(Class clazz) {
440:                    this .clazz = clazz;
441:                }
442:
443:                /**
444:                 * Creates an instance of the specified class.
445:                 *
446:                 * @param attribs the attributes (ignored)
447:                 * @return the new object
448:                 * @throws Exception if object creation fails
449:                 */
450:                public Object createObject(Attributes attribs) throws Exception {
451:                    return clazz.newInstance();
452:                }
453:            }
454:
455:            /**
456:             * A tiny inner class that allows the Configuration Factory to
457:             * let the digester construct FileConfiguration objects
458:             * that already have the correct base Path set.
459:             *
460:             */
461:            public class FileConfigurationFactory extends
462:                    DigesterConfigurationFactory {
463:                /**
464:                 * C'tor
465:                 *
466:                 * @param clazz The class which we should instantiate.
467:                 */
468:                public FileConfigurationFactory(Class clazz) {
469:                    super (clazz);
470:                }
471:
472:                /**
473:                 * Gets called by the digester.
474:                 *
475:                 * @param attributes the actual attributes
476:                 * @return the new object
477:                 * @throws Exception Couldn't instantiate the requested object.
478:                 */
479:                public Object createObject(Attributes attributes)
480:                        throws Exception {
481:                    FileConfiguration conf = createConfiguration(attributes);
482:                    conf.setBasePath(getBasePath());
483:                    return conf;
484:                }
485:
486:                /**
487:                 * Creates the object, a <code>FileConfiguration</code>.
488:                 *
489:                 * @param attributes the actual attributes
490:                 * @return the file configuration
491:                 * @throws Exception if the object could not be created
492:                 */
493:                protected FileConfiguration createConfiguration(
494:                        Attributes attributes) throws Exception {
495:                    return (FileConfiguration) super .createObject(attributes);
496:                }
497:            }
498:
499:            /**
500:             * A factory that returns an XMLPropertiesConfiguration for .xml files
501:             * and a PropertiesConfiguration for the others.
502:             *
503:             * @since 1.2
504:             */
505:            public class PropertiesConfigurationFactory extends
506:                    FileConfigurationFactory {
507:                /**
508:                 * Creates a new instance of <code>PropertiesConfigurationFactory</code>.
509:                 */
510:                public PropertiesConfigurationFactory() {
511:                    super (null);
512:                }
513:
514:                /**
515:                 * Creates the new configuration object. Based on the file name
516:                 * provided in the attributes either a <code>PropertiesConfiguration</code>
517:                 * or a <code>XMLPropertiesConfiguration</code> object will be
518:                 * returned.
519:                 *
520:                 * @param attributes the attributes
521:                 * @return the new configuration object
522:                 * @throws Exception if an error occurs
523:                 */
524:                protected FileConfiguration createConfiguration(
525:                        Attributes attributes) throws Exception {
526:                    String filename = attributes.getValue(ATTR_FILENAME);
527:
528:                    if (filename != null
529:                            && filename.toLowerCase().trim().endsWith(".xml")) {
530:                        return new XMLPropertiesConfiguration();
531:                    } else {
532:                        return new PropertiesConfiguration();
533:                    }
534:                }
535:            }
536:
537:            /**
538:             * A factory that returns an XMLPropertyListConfiguration for .xml files
539:             * and a PropertyListConfiguration for the others.
540:             *
541:             * @since 1.2
542:             */
543:            public class PropertyListConfigurationFactory extends
544:                    FileConfigurationFactory {
545:                /**
546:                 * Creates a new instance of <code>PropertyListConfigurationFactory</code>.
547:                 */
548:                public PropertyListConfigurationFactory() {
549:                    super (null);
550:                }
551:
552:                /**
553:                 * Creates the new configuration object. Based on the file name
554:                 * provided in the attributes either a <code>XMLPropertyListConfiguration</code>
555:                 * or a <code>PropertyListConfiguration</code> object will be
556:                 * returned.
557:                 *
558:                 * @param attributes the attributes
559:                 * @return the new configuration object
560:                 * @throws Exception if an error occurs
561:                 */
562:                protected FileConfiguration createConfiguration(
563:                        Attributes attributes) throws Exception {
564:                    String filename = attributes.getValue(ATTR_FILENAME);
565:
566:                    if (filename != null
567:                            && filename.toLowerCase().trim().endsWith(".xml")) {
568:                        return new XMLPropertyListConfiguration();
569:                    } else {
570:                        return new PropertyListConfiguration();
571:                    }
572:                }
573:            }
574:
575:            /**
576:             * A tiny inner class that allows the Configuration Factory to
577:             * let the digester construct JNDIConfiguration objects.
578:             */
579:            private class JNDIConfigurationFactory extends
580:                    DigesterConfigurationFactory {
581:                /**
582:                 * Creates a new instance of <code>JNDIConfigurationFactory</code>.
583:                 */
584:                public JNDIConfigurationFactory() {
585:                    super (JNDIConfiguration.class);
586:                }
587:            }
588:
589:            /**
590:             * A tiny inner class that allows the Configuration Factory to
591:             * let the digester construct SystemConfiguration objects.
592:             */
593:            private class SystemConfigurationFactory extends
594:                    DigesterConfigurationFactory {
595:                /**
596:                 * Creates a new instance of <code>SystemConfigurationFactory</code>.
597:                 */
598:                public SystemConfigurationFactory() {
599:                    super (SystemConfiguration.class);
600:                }
601:            }
602:
603:            /**
604:             * A simple data class that holds all information about a configuration
605:             * from the <code>&lt;additional&gt;</code> section.
606:             */
607:            public static class AdditionalConfigurationData {
608:                /** Stores the configuration object.*/
609:                private Configuration configuration;
610:
611:                /** Stores the location of this configuration in the global tree.*/
612:                private String at;
613:
614:                /**
615:                 * Returns the value of the <code>at</code> attribute.
616:                 *
617:                 * @return the at attribute
618:                 */
619:                public String getAt() {
620:                    return at;
621:                }
622:
623:                /**
624:                 * Sets the value of the <code>at</code> attribute.
625:                 *
626:                 * @param string the attribute value
627:                 */
628:                public void setAt(String string) {
629:                    at = string;
630:                }
631:
632:                /**
633:                 * Returns the configuration object.
634:                 *
635:                 * @return the configuration
636:                 */
637:                public Configuration getConfiguration() {
638:                    return configuration;
639:                }
640:
641:                /**
642:                 * Sets the configuration object. Note: Normally this method should be
643:                 * named <code>setConfiguration()</code>, but the name
644:                 * <code>addConfiguration()</code> is required by some of the digester
645:                 * rules.
646:                 *
647:                 * @param config the configuration to set
648:                 */
649:                public void addConfiguration(Configuration config) {
650:                    configuration = config;
651:                }
652:            }
653:
654:            /**
655:             * An internally used helper class for constructing the composite
656:             * configuration object.
657:             */
658:            public static class ConfigurationBuilder {
659:                /** Stores the composite configuration.*/
660:                private CompositeConfiguration config;
661:
662:                /** Stores a collection with the configs from the additional section.*/
663:                private Collection additionalConfigs;
664:
665:                /**
666:                 * Creates a new instance of <code>ConfigurationBuilder</code>.
667:                 */
668:                public ConfigurationBuilder() {
669:                    config = new CompositeConfiguration();
670:                    additionalConfigs = new LinkedList();
671:                }
672:
673:                /**
674:                 * Adds a new configuration to this object. This method is called by
675:                 * Digester.
676:                 *
677:                 * @param conf the configuration to be added
678:                 */
679:                public void addConfiguration(Configuration conf) {
680:                    config.addConfiguration(conf);
681:                }
682:
683:                /**
684:                 * Adds information about an additional configuration. This method is
685:                 * called by Digester.
686:                 *
687:                 * @param data the data about the additional configuration
688:                 */
689:                public void addAdditionalConfig(AdditionalConfigurationData data) {
690:                    additionalConfigs.add(data);
691:                }
692:
693:                /**
694:                 * Returns the final composite configuration.
695:                 *
696:                 * @return the final configuration object
697:                 */
698:                public CompositeConfiguration getConfiguration() {
699:                    if (!additionalConfigs.isEmpty()) {
700:                        Configuration unionConfig = createAdditionalConfiguration(additionalConfigs);
701:                        if (unionConfig != null) {
702:                            addConfiguration(unionConfig);
703:                        }
704:                        additionalConfigs.clear();
705:                    }
706:
707:                    return config;
708:                }
709:
710:                /**
711:                 * Creates a configuration object with the union of all properties
712:                 * defined in the <code>&lt;additional&gt;</code> section. This
713:                 * implementation returns a <code>HierarchicalConfiguration</code>
714:                 * object.
715:                 *
716:                 * @param configs a collection with
717:                 * <code>AdditionalConfigurationData</code> objects
718:                 * @return the union configuration (can be <b>null</b>)
719:                 */
720:                protected Configuration createAdditionalConfiguration(
721:                        Collection configs) {
722:                    HierarchicalConfiguration result = new HierarchicalConfiguration();
723:
724:                    for (Iterator it = configs.iterator(); it.hasNext();) {
725:                        AdditionalConfigurationData cdata = (AdditionalConfigurationData) it
726:                                .next();
727:                        result.addNodes(cdata.getAt(), createRootNode(cdata)
728:                                .getChildren());
729:                    }
730:
731:                    return result.isEmpty() ? null : result;
732:                }
733:
734:                /**
735:                 * Creates a configuration root node for the specified configuration.
736:                 *
737:                 * @param cdata the configuration data object
738:                 * @return a root node for this configuration
739:                 */
740:                private HierarchicalConfiguration.Node createRootNode(
741:                        AdditionalConfigurationData cdata) {
742:                    if (cdata.getConfiguration() instanceof  HierarchicalConfiguration) {
743:                        // we can directly use this configuration's root node
744:                        return ((HierarchicalConfiguration) cdata
745:                                .getConfiguration()).getRoot();
746:                    } else {
747:                        // transform configuration to a hierarchical root node
748:                        HierarchicalConfiguration hc = new HierarchicalConfiguration();
749:                        ConfigurationUtils.copy(cdata.getConfiguration(), hc);
750:                        return hc.getRoot();
751:                    }
752:                }
753:            }
754:
755:            /**
756:             * A special implementation of Digester's <code>CallMethodRule</code> that
757:             * is internally used for calling a file configuration's <code>load()</code>
758:             * method. This class difers from its ancestor that it catches all occuring
759:             * exceptions when the specified method is called. It then checks whether
760:             * for the corresponding configuration the optional attribute is set. If
761:             * this is the case, the exception will simply be ignored.
762:             *
763:             * @since 1.4
764:             */
765:            private static class CallOptionalMethodRule extends CallMethodRule {
766:                /** A flag whether the optional attribute is set for this node. */
767:                private boolean optional;
768:
769:                /**
770:                 * Creates a new instance of <code>CallOptionalMethodRule</code> and
771:                 * sets the name of the method to invoke.
772:                 *
773:                 * @param methodName the name of the method
774:                 */
775:                public CallOptionalMethodRule(String methodName) {
776:                    super (methodName);
777:                }
778:
779:                /**
780:                 * Checks if the optional attribute is set.
781:                 *
782:                 * @param attrs the attributes
783:                 * @throws Exception if an error occurs
784:                 */
785:                public void begin(Attributes attrs) throws Exception {
786:                    optional = attrs.getValue(ATTR_OPTIONAL) != null
787:                            && PropertyConverter.toBoolean(
788:                                    attrs.getValue(ATTR_OPTIONAL))
789:                                    .booleanValue();
790:                    super .begin(attrs);
791:                }
792:
793:                /**
794:                 * Calls the method. If the optional attribute was set, occurring
795:                 * exceptions will be ignored.
796:                 *
797:                 * @throws Exception if an error occurs
798:                 */
799:                public void end() throws Exception {
800:                    try {
801:                        super .end();
802:                    } catch (Exception ex) {
803:                        if (optional) {
804:                            log.warn(
805:                                    "Could not create optional configuration!",
806:                                    ex);
807:                        } else {
808:                            throw ex;
809:                        }
810:                    }
811:                }
812:            }
813:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.