You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2007/01/15 22:23:59 UTC

svn commit: r496498 - in /jakarta/commons/proper/configuration/trunk/src: java/org/apache/commons/configuration/DatabaseConfiguration.java test/org/apache/commons/configuration/TestDatabaseConfiguration.java

Author: oheger
Date: Mon Jan 15 13:23:58 2007
New Revision: 496498

URL: http://svn.apache.org/viewvc?view=rev&rev=496498
Log:
CONFIGURATION-245: DatabaseConfiguration will now generate error events in case on an internal error.

Modified:
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DatabaseConfiguration.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDatabaseConfiguration.java

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DatabaseConfiguration.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DatabaseConfiguration.java?view=diff&rev=496498&r1=496497&r2=496498
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DatabaseConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DatabaseConfiguration.java Mon Jan 15 13:23:58 2007
@@ -79,6 +79,7 @@
         this.valueColumn = valueColumn;
         this.name = name;
         setLogger(LogFactory.getLog(getClass()));
+        addErrorLogListener();  // log errors per default
     }
 
     /**
@@ -95,7 +96,14 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Returns the value of the specified property. If this causes a database
+     * error, an error event will be generated of type
+     * <code>EVENT_READ_PROPERTY</code> with the causing exception. The
+     * event's <code>propertyName</code> is set to the passed in property key,
+     * the <code>propertyValue</code> is undefined.
+     *
+     * @param key the key of the desired property
+     * @return the value of this property
      */
     public Object getProperty(String key)
     {
@@ -113,7 +121,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -145,7 +153,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_READ_PROPERTY, key, null, e);
         }
         finally
         {
@@ -156,7 +164,14 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Adds a property to this configuration. If this causes a database error,
+     * an error event will be generated of type <code>EVENT_ADD_PROPERTY</code>
+     * with the causing exception. The event's <code>propertyName</code> is
+     * set to the passed in property key, the <code>propertyValue</code>
+     * points to the passed in value.
+     *
+     * @param key the property key
+     * @param obj the value of the property to add
      */
     protected void addPropertyDirect(String key, Object obj)
     {
@@ -176,7 +191,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -192,7 +207,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_ADD_PROPERTY, key, obj, e);
         }
         finally
         {
@@ -202,7 +217,12 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Checks if this configuration is empty. If this causes a database error,
+     * an error event will be generated of type <code>EVENT_READ_PROPERTY</code>
+     * with the causing exception. Both the event's <code>propertyName</code>
+     * and <code>propertyValue</code> will be undefined.
+     *
+     * @return a flag whether this configuration is empty.
      */
     public boolean isEmpty()
     {
@@ -220,7 +240,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -238,7 +258,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_READ_PROPERTY, null, null, e);
         }
         finally
         {
@@ -250,7 +270,14 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Checks whether this configuration contains the specified key. If this
+     * causes a database error, an error event will be generated of type
+     * <code>EVENT_READ_PROPERTY</code> with the causing exception. The
+     * event's <code>propertyName</code> will be set to the passed in key, the
+     * <code>propertyValue</code> will be undefined.
+     *
+     * @param key the key to be checked
+     * @return a flag whether this key is defined
      */
     public boolean containsKey(String key)
     {
@@ -268,7 +295,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -284,7 +311,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_READ_PROPERTY, key, null, e);
         }
         finally
         {
@@ -296,7 +323,13 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Removes the specified value from this configuration. If this causes a
+     * database error, an error event will be generated of type
+     * <code>EVENT_CLEAR_PROPERTY</code> with the causing exception. The
+     * event's <code>propertyName</code> will be set to the passed in key, the
+     * <code>propertyValue</code> will be undefined.
+     *
+     * @param key the key of the property to be removed
      */
     public void clearProperty(String key)
     {
@@ -312,7 +345,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -326,7 +359,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_CLEAR_PROPERTY, key, null, e);
         }
         finally
         {
@@ -336,7 +369,11 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Removes all entries from this configuration. If this causes a database
+     * error, an error event will be generated of type
+     * <code>EVENT_CLEAR</code> with the causing exception. Both the
+     * event's <code>propertyName</code> and the <code>propertyValue</code>
+     * will be undefined.
      */
     public void clear()
     {
@@ -352,7 +389,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -365,7 +402,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_CLEAR, null, null, e);
         }
         finally
         {
@@ -375,7 +412,14 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Returns an iterator with the names of all properties contained in this
+     * configuration. If this causes a database
+     * error, an error event will be generated of type
+     * <code>EVENT_READ_PROPERTY</code> with the causing exception. Both the
+     * event's <code>propertyName</code> and the <code>propertyValue</code>
+     * will be undefined.
+     * @return an iterator with the contained keys (an empty iterator in case
+     * of an error)
      */
     public Iterator getKeys()
     {
@@ -393,7 +437,7 @@
 
         try
         {
-            conn = datasource.getConnection();
+            conn = getConnection();
 
             // bind the parameters
             pstmt = conn.prepareStatement(query.toString());
@@ -411,7 +455,7 @@
         }
         catch (SQLException e)
         {
-            getLogger().error(e.getMessage(), e);
+            fireError(EVENT_READ_PROPERTY, null, null, e);
         }
         finally
         {
@@ -423,6 +467,31 @@
     }
 
     /**
+     * Returns the used <code>DataSource</code> object.
+     *
+     * @return the data source
+     * @since 1.4
+     */
+    public DataSource getDatasource()
+    {
+        return datasource;
+    }
+
+    /**
+     * Returns a <code>Connection</code> object. This method is called when
+     * ever the database is to be accessed. This implementation returns a
+     * connection from the current <code>DataSource</code>.
+     *
+     * @return the <code>Connection</code> object to be used
+     * @throws SQLException if an error occurs
+     * @since 1.4
+     */
+    protected Connection getConnection() throws SQLException
+    {
+        return getDatasource().getConnection();
+    }
+
+    /**
      * Close a <code>Connection</code> and, <code>Statement</code>.
      * Avoid closing if null and hide any SQLExceptions that occur.
      *
@@ -447,4 +516,4 @@
             getLogger().error(e.getMessage(), e);
         }
     }
-}
+}
\ No newline at end of file

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDatabaseConfiguration.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDatabaseConfiguration.java?view=diff&rev=496498&r1=496497&r2=496498
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDatabaseConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDatabaseConfiguration.java Mon Jan 15 13:23:58 2007
@@ -18,6 +18,7 @@
 package org.apache.commons.configuration;
 
 import java.io.FileInputStream;
+import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Iterator;
 import java.util.List;
@@ -26,6 +27,8 @@
 
 import junit.framework.TestCase;
 
+import org.apache.commons.configuration.event.ConfigurationErrorEvent;
+import org.apache.commons.configuration.event.ConfigurationErrorListener;
 import org.apache.commons.configuration.test.HsqlDB;
 import org.apache.commons.dbcp.BasicDataSource;
 import org.dbunit.database.DatabaseConnection;
@@ -35,7 +38,7 @@
 import org.dbunit.operation.DatabaseOperation;
 
 /**
- * Test for database stored configurations.  Note, when running this Unit 
+ * Test for database stored configurations.  Note, when running this Unit
  * Test in Eclipse it sometimes takes a couple tries. Otherwise you may get
  * database is already in use by another process errors.
  *
@@ -48,10 +51,31 @@
     public final String DATABASE_USERNAME = "sa";
     public final String DATABASE_PASSWORD = "";
 
+    /** Constant for the configuration table.*/
+    private static final String TABLE = "configuration";
+
+    /** Constant for the multi configuration table.*/
+    private static final String TABLE_MULTI = "configurations";
+
+    /** Constant for the column with the keys.*/
+    private static final String COL_KEY = "key";
+
+    /** Constant for the column with the values.*/
+    private static final String COL_VALUE = "value";
+
+    /** Constant for the column with the configuration name.*/
+    private static final String COL_NAME = "name";
+
+    /** Constant for the name of the test configuration.*/
+    private static final String CONFIG_NAME = "test";
+
     private static HsqlDB hsqlDB = null;
 
     private DataSource datasource;
 
+    /** An error listener for testing whether internal errors occurred.*/
+    private TestErrorListener listener;
+
     protected void setUp() throws Exception
     {
         /*
@@ -59,9 +83,9 @@
          * use exception.
          */
         //Thread.sleep(1000);
-        
+
         // set up the datasource
-        
+
         if (hsqlDB == null)
         {
             hsqlDB = new HsqlDB(DATABASE_URL, DATABASE_DRIVER, "conf/testdb.script");
@@ -74,7 +98,7 @@
         datasource.setPassword(DATABASE_PASSWORD);
 
         this.datasource = datasource;
-        
+
 
         // prepare the database
         IDatabaseConnection connection = new DatabaseConnection(datasource.getConnection());
@@ -89,15 +113,98 @@
             connection.close();
         }
     }
-    
-    protected void tearDown() throws SQLException{
+
+    protected void tearDown() throws Exception{
         datasource.getConnection().commit();
         datasource.getConnection().close();
+
+        // if an error listener is defined, we check whether an error occurred
+        if(listener != null)
+        {
+            assertEquals("An internal error occurred", 0, listener.errorCount);
+        }
+        super.tearDown();
+    }
+
+    /**
+     * Creates a database configuration with default values.
+     *
+     * @return the configuration
+     */
+    private PotentialErrorDatabaseConfiguration setUpConfig()
+    {
+        return new PotentialErrorDatabaseConfiguration(datasource, TABLE,
+                COL_KEY, COL_VALUE);
+    }
+
+    /**
+     * Creates a database configuration that supports multiple configurations in
+     * a table with default values.
+     *
+     * @return the configuration
+     */
+    private DatabaseConfiguration setUpMultiConfig()
+    {
+        return new DatabaseConfiguration(datasource, TABLE_MULTI, COL_NAME,
+                COL_KEY, COL_VALUE, CONFIG_NAME);
+    }
+
+    /**
+     * Creates an error listener and adds it to the specified configuration.
+     *
+     * @param config the configuration
+     */
+    private void setUpErrorListener(PotentialErrorDatabaseConfiguration config)
+    {
+        // remove log listener to avoid exception longs
+        config.removeErrorListener((ConfigurationErrorListener) config
+                .getErrorListeners().iterator().next());
+        listener = new TestErrorListener();
+        config.addErrorListener(listener);
+        config.failOnConnect = true;
+    }
+
+    /**
+     * Prepares a test for a database error. Sets up a config and registers an
+     * error listener.
+     *
+     * @return the initialized configuration
+     */
+    private PotentialErrorDatabaseConfiguration setUpErrorConfig()
+    {
+        PotentialErrorDatabaseConfiguration config = setUpConfig();
+        setUpErrorListener(config);
+        return config;
+    }
+
+    /**
+     * Checks the error listener for an expected error. The properties of the
+     * error event will be compared with the expected values.
+     *
+     * @param type the expected type of the error event
+     * @param key the expected property key
+     * @param value the expected property value
+     */
+    private void checkErrorListener(int type, String key, Object value)
+    {
+        assertEquals("Wrong number of errors", 1, listener.errorCount);
+        assertEquals("Wrong event type", type, listener.event.getType());
+        assertTrue("Wrong event source",
+                listener.event.getSource() instanceof DatabaseConfiguration);
+        assertTrue("Wrong exception",
+                listener.event.getCause() instanceof SQLException);
+        assertTrue("Wrong property key", (key == null) ? listener.event
+                .getPropertyName() == null : key.equals(listener.event
+                .getPropertyName()));
+        assertTrue("Wrong property value", (value == null) ? listener.event
+                .getPropertyValue() == null : value.equals(listener.event
+                .getPropertyValue()));
+        listener = null; // mark as checked
     }
 
     public void testAddPropertyDirectSingle()
     {
-        DatabaseConfiguration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        DatabaseConfiguration config = setUpConfig();
         config.addPropertyDirect("key", "value");
 
         assertTrue("missing property", config.containsKey("key"));
@@ -105,7 +212,7 @@
 
     public void testAddPropertyDirectMultiple()
     {
-        DatabaseConfiguration config = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        DatabaseConfiguration config = setUpMultiConfig();
         config.addPropertyDirect("key", "value");
 
         assertTrue("missing property", config.containsKey("key"));
@@ -113,7 +220,7 @@
 
     public void testAddNonStringProperty()
     {
-        DatabaseConfiguration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        DatabaseConfiguration config = setUpConfig();
         config.addPropertyDirect("boolean", Boolean.TRUE);
 
         assertTrue("missing property", config.containsKey("boolean"));
@@ -121,7 +228,7 @@
 
     public void testGetPropertyDirectSingle()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config = setUpConfig();
 
         assertEquals("property1", "value1", config.getProperty("key1"));
         assertEquals("property2", "value2", config.getProperty("key2"));
@@ -130,7 +237,7 @@
 
     public void testGetPropertyDirectMultiple()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        Configuration config = setUpMultiConfig();
 
         assertEquals("property1", "value1", config.getProperty("key1"));
         assertEquals("property2", "value2", config.getProperty("key2"));
@@ -139,7 +246,7 @@
 
     public void testClearPropertySingle()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config = setUpConfig();
         config.clearProperty("key");
 
         assertFalse("property not cleared", config.containsKey("key"));
@@ -147,7 +254,7 @@
 
     public void testClearPropertyMultiple()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        Configuration config = setUpMultiConfig();
         config.clearProperty("key");
 
         assertFalse("property not cleared", config.containsKey("key"));
@@ -155,7 +262,7 @@
 
     public void testClearSingle()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config = setUpConfig();
         config.clear();
 
         assertTrue("configuration is not cleared", config.isEmpty());
@@ -163,7 +270,7 @@
 
     public void testClearMultiple()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        Configuration config = setUpMultiConfig();
         config.clear();
 
         assertTrue("configuration is not cleared", config.isEmpty());
@@ -171,7 +278,7 @@
 
     public void testGetKeysSingle()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config = setUpConfig();
         Iterator it = config.getKeys();
 
         assertEquals("1st key", "key1", it.next());
@@ -180,7 +287,7 @@
 
     public void testGetKeysMultiple()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        Configuration config = setUpMultiConfig();
         Iterator it = config.getKeys();
 
         assertEquals("1st key", "key1", it.next());
@@ -189,43 +296,43 @@
 
     public void testContainsKeySingle()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config = setUpConfig();
         assertTrue("missing key1", config.containsKey("key1"));
         assertTrue("missing key2", config.containsKey("key2"));
     }
 
     public void testContainsKeyMultiple()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        Configuration config = setUpMultiConfig();
         assertTrue("missing key1", config.containsKey("key1"));
         assertTrue("missing key2", config.containsKey("key2"));
     }
 
     public void testIsEmptySingle()
     {
-        Configuration config1 = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config1 = setUpConfig();
         assertFalse("The configuration is empty", config1.isEmpty());
     }
 
     public void testIsEmptyMultiple()
     {
-        Configuration config1 = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "test");
+        Configuration config1 = setUpMultiConfig();
         assertFalse("The configuration named 'test' is empty", config1.isEmpty());
 
-        Configuration config2 = new DatabaseConfiguration(datasource, "configurations", "name", "key", "value", "testIsEmpty");
+        Configuration config2 = new DatabaseConfiguration(datasource, TABLE_MULTI, COL_NAME, COL_KEY, COL_VALUE, "testIsEmpty");
         assertTrue("The configuration named 'testIsEmpty' is not empty", config2.isEmpty());
     }
-    
+
     public void testGetList()
     {
-        Configuration config1 = new DatabaseConfiguration(datasource, "configurationList", "key", "value");
+        Configuration config1 = new DatabaseConfiguration(datasource, "configurationList", COL_KEY, COL_VALUE);
         List list = config1.getList("key3");
         assertEquals(3,list.size());
-    }    
-    
+    }
+
     public void testGetKeys()
     {
-        Configuration config1 = new DatabaseConfiguration(datasource, "configurationList", "key", "value");
+        Configuration config1 = new DatabaseConfiguration(datasource, "configurationList", COL_KEY, COL_VALUE);
         Iterator i = config1.getKeys();
         assertTrue(i.hasNext());
         Object key = i.next();
@@ -235,7 +342,7 @@
 
     public void testClearSubset()
     {
-        Configuration config = new DatabaseConfiguration(datasource, "configuration", "key", "value");
+        Configuration config = setUpConfig();
 
         Configuration subset = config.subset("key1");
         subset.clear();
@@ -244,4 +351,133 @@
         assertFalse("the parent configuration is empty", config.isEmpty());
     }
 
+    /**
+     * Tests whether the configuration has already an error listener registered
+     * that is used for logging.
+     */
+    public void testLogErrorListener()
+    {
+        DatabaseConfiguration config = new DatabaseConfiguration(datasource,
+                TABLE, COL_KEY, COL_VALUE);
+        assertEquals("No error listener registered", 1, config
+                .getErrorListeners().size());
+    }
+
+    /**
+     * Tests handling of errors in getProperty().
+     */
+    public void testGetPropertyError()
+    {
+        setUpErrorConfig().getProperty("key1");
+        checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, "key1",
+                null);
+    }
+
+    /**
+     * Tests handling of errors in addPropertyDirect().
+     */
+    public void testAddPropertyError()
+    {
+        setUpErrorConfig().addProperty("key1", "value");
+        checkErrorListener(AbstractConfiguration.EVENT_ADD_PROPERTY, "key1",
+                "value");
+    }
+
+    /**
+     * Tests handling of errors in isEmpty().
+     */
+    public void testIsEmptyError()
+    {
+        assertTrue("Wrong return value for failure", setUpErrorConfig()
+                .isEmpty());
+        checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, null,
+                null);
+    }
+
+    /**
+     * Tests handling of errors in containsKey().
+     */
+    public void testContainsKeyError()
+    {
+        assertFalse("Wrong return value for failure", setUpErrorConfig()
+                .containsKey("key1"));
+        checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, "key1",
+                null);
+    }
+
+    /**
+     * Tests handling of errors in clearProperty().
+     */
+    public void testClearPropertyError()
+    {
+        setUpErrorConfig().clearProperty("key1");
+        checkErrorListener(AbstractConfiguration.EVENT_CLEAR_PROPERTY, "key1",
+                null);
+    }
+
+    /**
+     * Tests handling of errors in clear().
+     */
+    public void testClearError()
+    {
+        setUpErrorConfig().clear();
+        checkErrorListener(AbstractConfiguration.EVENT_CLEAR, null, null);
+    }
+
+    /**
+     * Tests handling of errors in getKeys().
+     */
+    public void testGetKeysError()
+    {
+        Iterator it = setUpErrorConfig().getKeys();
+        checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, null,
+                null);
+        assertFalse("Iteration is not empty", it.hasNext());
+    }
+
+    /**
+     * A specialized database configuration implementation that can be
+     * configured to throw an exception when obtaining a connection. This way
+     * database exceptions can be simulated.
+     */
+    static class PotentialErrorDatabaseConfiguration extends
+            DatabaseConfiguration
+    {
+        /** A flag whether a getConnection() call should fail. */
+        boolean failOnConnect;
+
+        public PotentialErrorDatabaseConfiguration(DataSource datasource,
+                String table, String keyColumn, String valueColumn)
+        {
+            super(datasource, table, keyColumn, valueColumn);
+        }
+
+        protected Connection getConnection() throws SQLException
+        {
+            if (failOnConnect)
+            {
+                throw new SQLException("Simulated DB error");
+            }
+            return super.getConnection();
+        }
+    }
+
+    /**
+     * A test error listener implementation that is used for finding out whether
+     * error events are correctly triggered.
+     */
+    static class TestErrorListener implements ConfigurationErrorListener
+    {
+        /** Stores the number of calls. */
+        int errorCount;
+
+        /** Stores the last error event. */
+        ConfigurationErrorEvent event;
+
+        public void configurationError(ConfigurationErrorEvent event)
+        {
+            errorCount++;
+            this.event = event;
+        }
+    }
 }



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