You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ep...@apache.org on 2004/01/16 15:56:45 UTC

cvs commit: jakarta-commons/configuration/src/test/org/apache/commons/configuration TestConfigurationXMLDocument.java

epugh       2004/01/16 06:56:45

  Modified:    configuration/xdocs changes.xml examples.xml overview.xml
               configuration/src/java/org/apache/commons/configuration
                        CompositeConfiguration.java
                        ConfigurationFactory.java
               configuration/conf testDigesterConfiguration2.xml
  Removed:     configuration/src/java/org/apache/commons/configuration
                        ConfigurationXMLDocument.java
               configuration/conf testConfigurationXMLDocument.xml
                        testDigesterCreateObject.xml
               configuration/src/test/org/apache/commons/configuration
                        TestConfigurationXMLDocument.java
  Log:
  - new class ConfigurationXMLDocument including test case
  - Removed className attribute in configuration definition file for
  ConfigurationFactory
  - New element <hierarchicalDom4j> in configuration definition file
  - Updates and enhancements of documentation
  
  Revision  Changes    Path
  1.3       +4 -0      jakarta-commons/configuration/xdocs/changes.xml
  
  Index: changes.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/xdocs/changes.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- changes.xml	24 Dec 2003 14:28:21 -0000	1.2
  +++ changes.xml	16 Jan 2004 14:56:45 -0000	1.3
  @@ -7,6 +7,10 @@
   
     <body>
       <release version="1.0-dev-4" date="">
  +	 <action dev="oheger" type="add">
  +      	ConfigurationFactory now supports the hierarchicalDom4j element in configuration 
  +      	definition file
  +     </action>     	
   	 <action dev="ebourg" type="update">
         	Change all Vector objects to List objects.
        </action>     	
  
  
  
  1.3       +10 -545   jakarta-commons/configuration/xdocs/examples.xml
  
  Index: examples.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/xdocs/examples.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- examples.xml	24 Dec 2003 14:28:21 -0000	1.2
  +++ examples.xml	16 Jan 2004 14:56:45 -0000	1.3
  @@ -428,13 +428,14 @@
   <configuration>
     <properties fileName="usergui.properties"/>
     <dom4j fileName="gui.xml"/>
  -  <hierarchicalDom4j fileName="tables.xml"/>
  +  <dom4j className="org.apache.commons.configuration.HierarchicalDOM4JConfiguration"
  +   fileName="tables.xml"/>
   </configuration>
   ]]>
   			</source>
   			<p>
  -				Note that one <code>dom4j</code> element was replaced by a
  -				<code>hierarchicalDom4j</code> element. This element tells the configuration
  +				Note the additional <code>className</code> attribute of the last
  +				<code>dom4j</code> element. This attribute tells the configuration
   				factory that not the default class for processing XML documents
   				should be used, but the class <code>HierarchicalDOM4JConfiguration</code>.
   				As the name implies this class is capable of saving the
  @@ -506,7 +507,7 @@
   				and do not have a complex structure the default XML configuration
   				class is suitable. If documents are more complex and their structure
   				is important, the hierarchy aware class should be used, which is
  -				selected by the <code>hierarchicalDom4j</code> element as
  +				enabled by an additional <code>className</code> attribute as
   				shown in the example configuration definition file above.
   			</p>
   		</subsection>
  @@ -604,8 +605,10 @@
     </override>
     
     <additional>
  -    <hierarchicalDom4j fileName="tables.xml"/>
  -    <hierarchicalDom4j fileName="tasktables.xml" at="tables"/>
  +    <dom4j className="org.apache.commons.configuration.HierarchicalDOM4JConfiguration"
  +     fileName="tables.xml"/>
  +    <dom4j className="org.apache.commons.configuration.HierarchicalDOM4JConfiguration"
  +     fileName="tasktables.xml" at="tables"/>
     </additional>
   </configuration>
   ]]>
  @@ -614,7 +617,7 @@
   			Compared to the older versions of this file a couple of changes has been
   			done. One major difference is that the elements for including configuration
   			sources are no longer direct children of the root element, but are now
  -			contained in either an <code>override</code> or <code>additonal</code>
  +			contained in either an <code>override</code> or <code>additional</code>
   			section. The names of these sections already imply their purpose.
   		</p>
   		<p>
  @@ -658,544 +661,6 @@
   			higher priority (otherwise they could not override the values of other
   			sources).
   		</p>
  -	</section>
  -	
  -	<section name="XML processing">
  -		<p>
  -			We have now loaded some configuration sources and accessed some of the
  -			properties. What else can we do? One additional feature provided by
  -			Configuration is its support for XML-like processing of <code>Configuration</code>
  -			objects that is implemented by the <code>ConfigurationXMLDocument</code>
  -			class. The XML format for data exchange has become very popular, so there
  -			are many use cases why you may want a XML-like view for your configuration.
  -			This section shows how to make use of these features.
  -		</p>
  -		<subsection name="Basic XML access">
  -			<p>
  -				When it comes to XML processing of configuration sources the
  -				<code>ConfigurationXMLDocument</code> class is usually involved.
  -				When an instance of this class is created a <code>Configuration</code>
  -				object is passed to the constructor. All operations executed on the
  -				instance are then related to this configuration or a subset of it.
  -			</p>
  -			<p>
  -				The most fundamental operation for treating a configuration source
  -				as a XML document is to request a <code>ConfigurationXMLReader</code>
  -				object from the <code>ConfigurationXMLDocument</code> instance.
  -				The object returned by this method implements the
  -				<code>org.xml.sax.XMLReader</code> interface and thus is a SAX 2
  -				conform XML parser. This parser can then be passed to components
  -				that can deal with SAX events. The following snippet shows how such
  -				a SAX parser can be obtained:
  -			</p>
  -			<source>
  -<![CDATA[
  -ConfigurationXMLDocument configDoc = new ConfigurationXMLDocument(config);
  -XMLReader reader = configDoc.createXMLReader();
  -
  -// or:
  -// XMLReader reader = configDoc.createXMLReader("tables");
  -// Now do something with the reader
  -...
  -]]>
  -			</source>
  -			<p>
  -				As this example shows it is either possible to obtain a reader object
  -				for the whole configuration or for a subset of it. The obtained object
  -				can now be used where ever a SAX parser is supported. There is
  -				only one thing to mention: The <code>XMLReader</code> returned
  -				by <code>createXMLReader()</code> has been initialized with the
  -				configuration source (or a subset of it) stored in the
  -				<code>ConfigurationXMLDocument</code> instance. If now one of the
  -				<code>parse()</code> methods is called, the passed in argument,
  -				which usually specifies the input source to parse, is ignored. This
  -				information is unnecessary because all parsing is always done on
  -				the associated <code>Configuration</code> object. Later in this section
  -				this fact should become clearer.
  -			</p>
  -		</subsection>
  -		<subsection name="Working with documents">
  -			<p>
  -				SAX may be the most efficient, but it is surely not the most convenient
  -				way of XML processing. If a document with a complex structure is to
  -				be navigated, a DOM based approach is usually more suitable.
  -			</p>
  -			<p>
  -				<code>ConfigurationXMLDocument</code> provides a couple of
  -				overloaded <code>getDocument()</code> methods that return a dom4j
  -				<code>Document</code> object. The arguments that can be passed to
  -				these methods allow to select a subset of the configuration source and
  -				to specify the name of the resulting document's root element. The following
  -				code fragment provides an example:
  -			</p>
  -			<source>
  -<![CDATA[
  -ConfigurationXMLDocument configDoc = new ConfigurationXMLDocument(config);
  -Document doc = configDoc.getDocument("tables", "database");
  -...
  -]]>
  -			</source>
  -			<p>
  -				The <code>Document</code> returned here contains all data below the
  -				<em>tables</em> section, i.e. it will have the root element <em>database</em>
  -				with three <em>table</em> elements as children. In addition to the
  -				<code>getDocument()</code> methods there is also a set of
  -				<code>getW3cDocument()</code> methods. These methods act in an
  -				analogous way, but return a <code>org.w3c.dom.Document</code> object
  -				rather than a dom4j document.
  -			</p>
  -			<p>
  -				Once a DOM document has been obtained the whole world of DOM processing
  -				is open. Especially dom4j allows for powerful and convenient manipulations,
  -				e.g. the document could be transformed using a stylesheet or written to
  -				a file. If a configuration source or parts of it should simply be saved as
  -				a XML document, there is an even easier way: the <code>write()</code>
  -				methods of <code>ConfigurationXMLDocument</code>. Let's assume our
  -				example application wants to send its database table definitions to an
  -				external tool, maybe to initialize the database schema. The following code
  -				shows how an XML file with this information could be written:
  -			</p>
  -			<source>
  -<![CDATA[
  -ConfigurationXMLDocument configDoc = new ConfigurationXMLDocument(config);
  -Writer out = null;
  -try
  -{
  -    out = new BufferedWriter(new FileWriter("tabledef.xml"));
  -    configDoc.write(out, "tables", "database");
  -}
  -finally
  -{
  -    out.close();
  -}
  -]]>
  -			</source>
  -		</subsection>
  -		<subsection name="Calling Digester">
  -			<p>
  -				<em>Commons Digester</em> is another Apache Jakarta project that
  -				implements a powerful engine for processing XML documents. In this section
  -				we will make use of Digester to transform the table definitions into a
  -				corresponding object model. For this tutorial the interesting part is
  -				the stuff related to the communication with Digester; more information
  -				about Digester and its features can be found at the homepage of the
  -				Digester project.
  -			</p>
  -			<p>
  -				We start with with the definition of a set of beans that will later store
  -				information about the database tables and their fields. To keep this
  -				example short these are very simple classes with hardly more than
  -				a couple of getter and setter methods. As you can see there are
  -				corresponding properties for all elements that can appear in the
  -				table configuration.
  -			</p>
  -			<source>
  -<![CDATA[
  -public class TestConfigurationXMLDocument
  -{
  -    /** Stores the tables.*/
  -    private ArrayList tables;
  -    
  -    /**
  -     * Adds a new table object. Called by Digester.
  -     * @param table the new table
  -     */
  -    public void addTable(Table table)
  -    {
  -        tables.add(table);
  -    }
  -
  -    /**
  -     * A simple bean class for storing information about a table field.
  -     * Used for the Digester test.
  -     */
  -    public static class TableField
  -    {
  -        private String name;
  -        private String type;
  -        
  -        public String getName()
  -        {
  -            return name;
  -        }
  -
  -        public String getType()
  -        {
  -            return type;
  -        }
  -
  -        public void setName(String string)
  -        {
  -            name = string;
  -        }
  -
  -        public void setType(String string)
  -        {
  -            type = string;
  -        }
  -    }
  -    
  -    /**
  -     * A simple bean class for storing information about a database table.
  -     * Used for the Digester test.
  -     */
  -    public static class Table
  -    {
  -        /** Stores the list of fields.*/
  -        private ArrayList fields;
  -        
  -        /** Stores the table name.*/
  -        private String name;
  -        
  -        /** Stores the table type.*/
  -        private String tableType;
  -        
  -        public Table()
  -        {
  -            fields = new ArrayList();
  -        }
  -        
  -        public String getName()
  -        {
  -            return name;
  -        }
  -
  -        public String getTableType()
  -        {
  -            return tableType;
  -        }
  -
  -        public void setName(String string)
  -        {
  -            name = string;
  -        }
  -
  -        public void setTableType(String string)
  -        {
  -            tableType = string;
  -        }
  -        
  -        /**
  -         * Adds a field.
  -         * @param field the new field
  -         */
  -        public void addField(TableField field)
  -        {
  -            fields.add(field);
  -        }
  -        
  -        /**
  -         * Returns the field with the given index.
  -         * @param idx the index
  -         * @return the field with this index
  -         */
  -        public TableField getField(int idx)
  -        {
  -            return (TableField) fields.get(idx);
  -        }
  -        
  -        /**
  -         * Returns the number of fields.
  -         * @return the number of fields
  -         */
  -        public int size()
  -        {
  -            return fields.size();
  -        }
  -    }
  -}
  -]]>
  -			</source>
  -			<p>
  -				While <code>TableField</code> is almost trivial, <code>Table</code>
  -				provides the ability of storing a number of field objects in an internal
  -				collection. The test class also defines a collection that will later
  -				store the <code>Table</code> objects created from the configuration.
  -			</p>
  -			<p>
  -				To pass the table configuration to Digester we have to
  -				<ol>
  -					<li>
  -						Ask our <code>ConfigurationXMLDocument</code> instance for
  -						a <code>XMLReader</code> for the <em>tables</em> section.
  -					</li>
  -					<li>
  -						Construct a new Digester object and pass this XML reader to
  -						the constructor.
  -					</li>
  -					<li>
  -						Initialize the Digester instance with the necessary processing rules
  -						to create a corresponding object hierarchy for the table definitions.
  -					</li>
  -					<li>
  -						Call the Digester's <code>parse()</code> method to initiate
  -						processing.
  -					</li>
  -				</ol>
  -				The following listing shows the implementation of these steps:
  -			</p>
  -			<source>
  -<![CDATA[
  -    public void testCallDigesterComplex() throws Exception
  -    {
  -        Digester digester = 
  -            new Digester(configDoc.createXMLReader("tables"));
  -        digester.addObjectCreate("config/table", Table.class);
  -        digester.addSetProperties("config/table");
  -        digester.addCallMethod("config/table/name", "setName", 0);
  -        digester.addObjectCreate("config/table/fields/field", TableField.class);
  -        digester.addCallMethod("config/table/fields/field/name",
  -            "setName", 0);
  -        digester.addCallMethod("config/table/fields/field/type",
  -            "setType", 0);
  -        digester.addSetNext("config/table/fields/field",
  -            "addField", TableField.class.getName());
  -        digester.addSetNext("config/table", "addTable", Table.class.getName());
  -        
  -        digester.push(this);
  -        digester.parse("config");
  -    }
  -]]>
  -			</source>
  -			<p>
  -				At the beginning of this listing <code>createXMLReader()</code>
  -				is called on the <code>ConfigurationXMLDocument</code> instance
  -				to obtain a SAX parser for the configuration subset with the table
  -				definitions. When the Digester object is created this parser is passed
  -				to its constructor.
  -			</p>
  -			<p>
  -				The major part of the fragment deals with setting up the necessary
  -				Digester rules. Details for that can be found in the Digester documentation.
  -				In short we define rules to create <code>Table</code> and
  -				<code>TableField</code> objects when the corresponding XML elements
  -				are detected. The newly created objects are initialized with the
  -				properties defined in the XML code. Then it is ensured that a new
  -				<code>TableField</code> object is added to a <code>Table</code>
  -				and that for each new <code>Table</code> object the
  -				<code>addTable()</code> method of the test class is invoked.
  -				This all conforms to the default usage pattern of Digester, only two
  -				points should be noticed:
  -			</p>
  -			<p>
  -				<ul>
  -					<li>
  -						The match strings for all Digester rules have the prefix
  -						<em>config/table</em>. The reason for this is that the XML document
  -						that is generated by the SAX parser has a corresponding structure.
  -						Remember when we called <code>createXMLReader()</code>, we
  -						specified the string <em>tables</em> as argument. This means that
  -						the resulting document will have all the content that can be found
  -						in the configuration under the key <em>tables</em>, which happens
  -						to be three <em>table</em> elements with their corresponding
  -						children. The root element of this document is named <em>config</em>.
  -						This is the default name of the root element if no other name is
  -						specified. If we had called <code>createXMLReader("tables", "tabledef")</code>,
  -						the root element would have been named <em>tabledef</em> and
  -						we would have to use match strings of the form <em>tabledef/table</em>.
  -					</li>
  -					<li>
  -						The call of the Digester's <code>parse()</code> method is a little
  -						strange because we only pass in the string <em>config</em> as
  -						argument. Fact is that if a <code>XMLReader</code> obtained
  -						from <code>ConfigurationXMLDocument</code> is involved, the
  -						parameter of the <code>parse()</code> method is completely
  -						ignored. The reader always refers to the configuration source it
  -						was constructed for. So we could have used an arbitrary string.
  -					</li>
  -				</ul>
  -			</p>
  -			<p>
  -				After the <code>parse()</code> method returns the <code>tables</code>
  -				collection of the test class contains three <code>Table</code> objects
  -				with all information specified in the configuration.
  -			</p>
  -		</subsection>
  -		<subsection name="Calling Digester for creating simple objects">
  -			<p>
  -				If an application's configuration defines complex objects that should
  -				be instantiated using Digester it will usually be necessary to provide
  -				specific Digester rules as shown in the last section. But another
  -				use case is to create an object whose class name is defined in the
  -				configuration and to perform some simple initialization on it.
  -			</p>
  -			<p>
  -				Imagine the example database application wants to open a connection to
  -				a database. Because it is a very sophisticated application it supports
  -				lots of different databases. To achieve this there is an abstract
  -				<code>ConnectionInfo</code> class that provides typical connect
  -				properties (such as user name, password and the name of the database)
  -				and an abstract <code>connect()</code> method, which establishes
  -				the connection to the database:
  -			</p>
  -			<source>
  -<![CDATA[
  -    public abstract class ConnectionInfo
  -    {
  -        private String dsn;
  -        private String user;
  -        private String passwd;
  -        
  -        public String getDsn()
  -        {
  -            return dsn;
  -        }
  -
  -        public String getPasswd()
  -        {
  -            return passwd;
  -        }
  -
  -        public String getUser()
  -        {
  -            return user;
  -        }
  -
  -        public void setDsn(String string)
  -        {
  -            dsn = string;
  -        }
  -
  -        public void setPasswd(String string)
  -        {
  -            passwd = string;
  -        }
  -
  -        public void setUser(String string)
  -        {
  -            user = string;
  -        }
  -        
  -        /**
  -         * Creates a connection to a database.
  -         * Must be defined in sub classes.
  -         * @return the created connection
  -         */
  -        public abstract Connection createConnection() throws SQLException;
  -    }
  -]]>
  -			</source>
  -			<p>
  -				There are now some sub classes of this class, one for each supported
  -				database with a proper implementation of <code>createConnection()</code>.
  -				When the example application is run it does not know from start,
  -				which database it has to access. Instead it determines the database
  -				driver class from a configuration property, creates an instance of it,
  -				and uses it to obtain a connection. For this use case the
  -				<code>callDigester()</code> method of <code>ConfigurationXMLDocument</code>
  -				was designed.
  -			</p>
  -			<p>
  -				To demonstrate this feature we start with an additional configuration source
  -				that defines the connection of the database to be used. We call it
  -				<code>connection.xml</code>.
  -			</p>
  -			<source>
  -<![CDATA[
  -<?xml version="1.0" encoding="UTF-8"?>
  -<configuration>
  -	<connection>
  -		<class name="myapp.ConnectionInfoOracle">
  -			<property name="dsn" value="MyData"/>
  -			<property name="user" value="scott"/>
  -			<property name="passwd" value="tiger"/>
  -		</class>
  -	</connection>
  -</configuration>
  -]]>
  -			</source>
  -			<p>
  -				This configuration file shows the typical structure of XML code
  -				that defines an object to be created using Digester: There must be
  -				a <code>class</code> element with a <code>name</code> attribute
  -				defining the full qualified name of the class to be instantiated. In the
  -				body of the <code>class</code> element there can be an arbitrary
  -				number of <code>property</code> elements. Each element defines
  -				the name and value of a property to be set, so Digester will call a
  -				corresponding setter method on the bean just created. Here we set
  -				properties with the names <em>dsn, user</em> and <em>passwd</em>.
  -				As you can see, our <code>ConnectionInfo</code> base class has
  -				getter and setter methods for exactly these properties. We have now to
  -				include this additional configuration file in our configuration definition file:
  -			</p>
  -  			<source>
  -<![CDATA[
  -<?xml version="1.0" encoding="ISO-8859-1" ?>
  -<!-- Configuration definition file that demonstrates the
  -     override and additional sections -->
  -
  -<configuration>
  -  <override>
  -    <properties fileName="usergui.properties"/>
  -    <dom4j fileName="gui.xml"/>
  -  </override>
  -  
  -  <additional>
  -    <hierarchicalDom4j fileName="tables.xml"/>
  -    <hierarchicalDom4j fileName="tasktables.xml" at="tables"/>
  -    <hierarchicalDom4j fileName="connection.xml"/>
  -  </additional>
  -</configuration>
  -]]>
  -			</source>
  -			<p>
  -				After that it is now quite easy to obtain an object with information
  -				about a database connection. The following code fragment shows
  -				how a connection can be opened (it assumes that the <code>Configuration</code>
  -				object obtained from the configuration factory is stored in a variable named
  -				<code>config</code>).
  -			</p>
  -  			<source>
  -<![CDATA[
  -ConfigurationXMLDocument configDoc = new ConfigurationXMLDocument(config);
  -ConnectionInfo connInfo = (ConnectionInfo) configDoc.callDigester("connection");
  -Connection conn = connInfo.createConnection();
  -]]>
  -			</source>
  -		</subsection>
  -		<subsection name="Some caveats">
  -			<p>
  -				At the end of this section about <code>ConfigurationXMLDocument</code>
  -				some notes about points a developer should be aware of are provided:
  -			</p>
  -			<p>
  -				<ul>
  -					<li>
  -						The class should not be used on the <code>Configuration</code>
  -						object obtained from <code>ConfigurationFactory</code> as a
  -						whole. Because this configuration can contain multiple configuration
  -						sources including those that override other properties the results
  -						are probably not what you expect. You can of course pass such a
  -						composite configuration to the constructor of
  -						<code>ConfigurationXMLDocument</code>, but you should then,
  -						when you call methods on this instance, always provide a
  -						configuration key that selects certain parts of the configuration.
  -					</li>
  -					<li>
  -						The XML processing abilities of the class naturally work best
  -						when a <code>HierarchicalConfiguration</code> object is
  -						involved. There is also support for other types of configuration
  -						sources, but this will work well only for very simple properties.
  -						The problem here is the loss of information concerning the
  -						structure of the properties (as was explained in an earlier secion). 
  -						So if you read a configuration source
  -						using the <code>dom4j</code> element rather than the
  -						<code>hierarchicalDom4j</code> element, XML documents
  -						generated by <code>ConfigurationXMLDocument</code> may
  -						look wired; the same is true for <code>properties</code>
  -						elements.
  -					</li>
  -					<li>
  -						If you read a XML configuration file and then save it again
  -						using <code>ConfigurationXMLDocument.write()</code> the
  -						result is not guaranteed to be identic to the original file.
  -						While the document structure is kept (i.e. the relation between
  -						elements and their children), there may be differences in the
  -						order in which elements are written.
  -					</li>
  -				</ul>
  -			</p>
  -		</subsection>
   	</section>
   </body>
   
  
  
  
  1.2       +6 -6      jakarta-commons/configuration/xdocs/overview.xml
  
  Index: overview.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/xdocs/overview.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- overview.xml	23 Dec 2003 15:09:05 -0000	1.1
  +++ overview.xml	16 Jan 2004 14:56:45 -0000	1.2
  @@ -67,9 +67,9 @@
   <?xml version="1.0" encoding="ISO-8859-1" ?>
   
   <configuration>
  -  <jndi prefix="java:comp/env"/>
  -  <properties fileName="conf/test.properties"/>
  -  <dom4j fileName="conf/test.xml"/>
  +  <jndi className="org.apache.commons.configuration.JNDIConfiguration" prefix="java:comp/env"/>
  +  <properties className="org.apache.commons.configuration.PropertiesConfiguration" fileName="conf/test.properties"/>
  +  <dom4j className="org.apache.commons.configuration.DOM4JConfiguration" fileName="conf/test.xml"/>
   </configuration>
   ]]>   
           </source>
  @@ -96,7 +96,7 @@
       	<subsection name="Classic Properties File">
           <source>
   <![CDATA[       
  -  <properties fileName="conf/test.properties"/>
  +  <properties className="org.apache.commons.configuration.PropertiesConfiguration" fileName="conf/test.properties"/>
   ]]>   
           </source>
           <p>
  @@ -106,7 +106,7 @@
       	<subsection name="XML Properties File">
           <source>
   <![CDATA[       
  -  <dom4j fileName="conf/test.xml"/>
  +  <dom4j className="org.apache.commons.configuration.DOM4JConfiguration" fileName="conf/test.xml"/>
   ]]>   
           </source>    	
           <p>
  @@ -136,7 +136,7 @@
       	<subsection name="JNDI Properties File">
           <source>
   <![CDATA[       
  -  <jndi prefix="java:comp/env"/>
  +  <jndi className="org.apache.commons.configuration.JNDIConfiguration" prefix="java:comp/env"/>
   ]]>   
           </source>    	
           <p>
  
  
  
  1.3       +2 -6      jakarta-commons/configuration/src/java/org/apache/commons/configuration/CompositeConfiguration.java
  
  Index: CompositeConfiguration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/CompositeConfiguration.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CompositeConfiguration.java	24 Dec 2003 14:28:22 -0000	1.2
  +++ CompositeConfiguration.java	16 Jan 2004 14:56:45 -0000	1.3
  @@ -271,8 +271,6 @@
       {
           CompositeConfiguration subsetCompositeConfiguration =
               new CompositeConfiguration();
  -        Configuration subConf = null;
  -        int count = 0;
           for (ListIterator i = configList.listIterator(); i.hasNext();)
           {
               Configuration config = (Configuration) i.next();
  @@ -280,11 +278,9 @@
               if (subset != null)
               {
                   subsetCompositeConfiguration.addConfiguration(subset);
  -                subConf = subset;
  -                count++;
               }
           }
  -        return (count == 1) ? subConf : subsetCompositeConfiguration;
  +        return subsetCompositeConfiguration;
       }
       /**
       * Get a float associated with the given configuration key.
  
  
  
  1.3       +18 -11    jakarta-commons/configuration/src/java/org/apache/commons/configuration/ConfigurationFactory.java
  
  Index: ConfigurationFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/ConfigurationFactory.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ConfigurationFactory.java	24 Dec 2003 14:28:22 -0000	1.2
  +++ ConfigurationFactory.java	16 Jan 2004 14:56:45 -0000	1.3
  @@ -291,12 +291,6 @@
               additional);
           setupDigesterInstance(
               digester,
  -            matchString + "hierarchicalDom4j",
  -            new BasePathConfigurationFactory(HierarchicalDOM4JConfiguration.class),
  -            METH_LOAD,
  -            additional);
  -        setupDigesterInstance(
  -            digester,
               matchString + "jndi",
               new JNDIConfigurationFactory(),
               null,
  @@ -418,13 +412,17 @@
   
       /**
        * A base class for digester factory classes. This base class maintains
  -     * a default class for the objects to be created.
  +     * a default class for the objects to be created. It also supports a
  +     * <code>className</code> attribute for specifying a different class.
        * There will be sub classes for specific configuration implementations.
        */
       public class DigesterConfigurationFactory
           extends AbstractObjectCreationFactory
           implements ObjectCreationFactory
       {
  +        /** Constant for the className attribute.*/
  +        protected static final String ATTR_CLASSNAME = "className";
  +
           /** Actual class to use. */
           private Class clazz;
   
  @@ -438,14 +436,23 @@
           }
   
           /**
  -         * Creates an instance of the specified class.
  -         * @param attribs the attributes (ignored)
  +         * Creates an instance of the specified class. If the passed in
  +         * attributes contain a <code>className</code> attribute, the value of
  +         * this attribute is interpreted as the full qualified class name of
  +         * the class to be instantiated. Otherwise the default class is used.
  +         * @param attribs the attributes
            * @return the new object
            * @exception Exception if object creation fails
            */
           public Object createObject(Attributes attribs) throws Exception
           {
  -            return clazz.newInstance();
  +            Class actCls;
  +            
  +            int idx = attribs.getIndex(ATTR_CLASSNAME);
  +            actCls = (idx < 0) ? clazz :
  +            Class.forName(attribs.getValue(idx));
  +
  +            return actCls.newInstance();
           }
       }
   
  
  
  
  1.2       +2 -2      jakarta-commons/configuration/conf/testDigesterConfiguration2.xml
  
  Index: testDigesterConfiguration2.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/conf/testDigesterConfiguration2.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- testDigesterConfiguration2.xml	23 Dec 2003 15:09:05 -0000	1.1
  +++ testDigesterConfiguration2.xml	16 Jan 2004 14:56:45 -0000	1.2
  @@ -4,8 +4,8 @@
   
   <configuration>
     <additional>
  -    <hierarchicalDom4j fileName="testHierarchicalDOM4JConfiguration.xml"/>
  -    <hierarchicalDom4j fileName="testDigesterConfigurationInclude1.xml" at="tables"/>
  +    <dom4j className="org.apache.commons.configuration.HierarchicalDOM4JConfiguration" fileName="testHierarchicalDOM4JConfiguration.xml"/>
  +    <dom4j className="org.apache.commons.configuration.HierarchicalDOM4JConfiguration" fileName="testDigesterConfigurationInclude1.xml" at="tables"/>
       <properties fileName="testDigesterConfigurationInclude2.properties" at="mail"/>
     </additional>
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org