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