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    package org.apache.commons.configuration;
018    
019    import java.io.File;
020    import java.io.FileInputStream;
021    import java.sql.Connection;
022    
023    import javax.sql.DataSource;
024    
025    import org.apache.commons.configuration.test.HsqlDB;
026    import org.apache.commons.dbcp.BasicDataSource;
027    import org.dbunit.database.DatabaseConnection;
028    import org.dbunit.database.IDatabaseConnection;
029    import org.dbunit.dataset.IDataSet;
030    import org.dbunit.dataset.xml.XmlDataSet;
031    import org.dbunit.operation.DatabaseOperation;
032    
033    /**
034     * A helper class for performing tests for {@link DatabaseConfiguration}. This
035     * class maintains an in-process database that stores configuration data and can
036     * be accessed from a {@link DatabaseConfiguration} instance. Constants for
037     * table and column names and database connection settings are provided, too.
038     *
039     * @version $Id: DatabaseConfigurationTestHelper.java 1222447 2011-12-22 20:59:44Z oheger $
040     */
041    public class DatabaseConfigurationTestHelper
042    {
043        /** Constant for the JDBC driver class. */
044        public final String DATABASE_DRIVER = "org.hsqldb.jdbcDriver";
045    
046        /** Constant for the connection URL. */
047        public final String DATABASE_URL = "jdbc:hsqldb:mem:testdb";
048    
049        /** Constant for the DB user name. */
050        public final String DATABASE_USERNAME = "sa";
051    
052        /** Constant for the DB password. */
053        public final String DATABASE_PASSWORD = "";
054    
055        /** Constant for the configuration table. */
056        public static final String TABLE = "configuration";
057    
058        /** Constant for the multi configuration table. */
059        public static final String TABLE_MULTI = "configurations";
060    
061        /** Constant for the column with the keys. */
062        public static final String COL_KEY = "key";
063    
064        /** Constant for the column with the values. */
065        public static final String COL_VALUE = "value";
066    
067        /** Constant for the column with the configuration name. */
068        public static final String COL_NAME = "name";
069    
070        /** Constant for the name of the test configuration. */
071        public static final String CONFIG_NAME = "test";
072    
073        /** Stores the in-process database. */
074        private HsqlDB hsqlDB;
075    
076        /** The data source. */
077        private DataSource datasource;
078    
079        /**
080         * The auto-commit mode for the connections created by the managed data
081         * source.
082         */
083        private boolean autoCommit = true;
084    
085        /**
086         * Returns the auto-commit mode of the connections created by the managed
087         * data source.
088         *
089         * @return the auto-commit mode
090         */
091        public boolean isAutoCommit()
092        {
093            return autoCommit;
094        }
095    
096        /**
097         * Sets the auto-commit mode of the connections created by the managed data
098         * source.
099         *
100         * @param autoCommit the auto-commit mode
101         */
102        public void setAutoCommit(boolean autoCommit)
103        {
104            this.autoCommit = autoCommit;
105        }
106    
107        /**
108         * Initializes this helper object. This method can be called from a
109         * {@code setUp()} method of a unit test class. It creates the database
110         * instance if necessary.
111         *
112         * @throws Exception if an error occurs
113         */
114        public void setUp() throws Exception
115        {
116            File script = ConfigurationAssert.getTestFile("testdb.script");
117            hsqlDB = new HsqlDB(DATABASE_URL, DATABASE_DRIVER, script.getAbsolutePath());
118        }
119    
120        /**
121         * Frees the resources used by this helper class. This method can be called
122         * by a {@code tearDown()} method of a unit test class.
123         *
124         * @throws Exception if an error occurs
125         */
126        public void tearDown() throws Exception
127        {
128            if (datasource != null)
129            {
130                datasource.getConnection().close();
131            }
132            hsqlDB.close();
133        }
134    
135        /**
136         * Creates a database configuration with default values.
137         *
138         * @return the configuration
139         */
140        public DatabaseConfiguration setUpConfig()
141        {
142            return new DatabaseConfiguration(getDatasource(), TABLE, COL_KEY,
143                    COL_VALUE, !isAutoCommit());
144        }
145    
146        /**
147         * Creates a database configuration that supports multiple configurations in
148         * a table with default values.
149         *
150         * @return the configuration
151         */
152        public DatabaseConfiguration setUpMultiConfig()
153        {
154            return setUpMultiConfig(CONFIG_NAME);
155        }
156    
157        /**
158         * Creates a database configuration that supports multiple configurations in
159         * a table and sets the specified configuration name.
160         *
161         * @param configName the name of the configuration
162         * @return the configuration
163         */
164        public DatabaseConfiguration setUpMultiConfig(String configName)
165        {
166            return new DatabaseConfiguration(getDatasource(), TABLE_MULTI,
167                    COL_NAME, COL_KEY, COL_VALUE, configName, !isAutoCommit());
168        }
169    
170        /**
171         * Returns the {@code DataSource} managed by this class. The data
172         * source is created on first access.
173         *
174         * @return the {@code DataSource}
175         */
176        public DataSource getDatasource()
177        {
178            if (datasource == null)
179            {
180                try
181                {
182                    datasource = setUpDataSource();
183                }
184                catch (Exception ex)
185                {
186                    throw new ConfigurationRuntimeException(
187                            "Could not create data source", ex);
188                }
189            }
190            return datasource;
191        }
192    
193        /**
194         * Creates the internal data source. This method also initializes the
195         * database.
196         *
197         * @return the data source
198         * @throws Exception if an error occurs
199         */
200        private DataSource setUpDataSource() throws Exception
201        {
202            BasicDataSource ds = new BasicDataSource();
203            ds.setDriverClassName(DATABASE_DRIVER);
204            ds.setUrl(DATABASE_URL);
205            ds.setUsername(DATABASE_USERNAME);
206            ds.setPassword(DATABASE_PASSWORD);
207            ds.setDefaultAutoCommit(isAutoCommit());
208    
209            // prepare the database
210            Connection conn = ds.getConnection();
211            IDatabaseConnection connection = new DatabaseConnection(conn);
212            IDataSet dataSet = new XmlDataSet(new FileInputStream(
213                    ConfigurationAssert.getTestFile("dataset.xml")));
214    
215            try
216            {
217                DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
218            }
219            finally
220            {
221                if (!isAutoCommit())
222                {
223                    conn.commit();
224                }
225                connection.close();
226            }
227    
228            return ds;
229        }
230    }