View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  package org.dbunit;
23  
24  import java.io.File;
25  import java.io.FileReader;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.sql.Connection;
29  import java.sql.DriverManager;
30  import java.util.Properties;
31  import java.util.concurrent.Callable;
32  
33  import org.dbunit.database.DatabaseConfig;
34  import org.dbunit.database.DatabaseConnection;
35  import org.dbunit.database.IDatabaseConnection;
36  import org.dbunit.dataset.IDataSet;
37  import org.dbunit.dataset.xml.XmlDataSet;
38  import org.dbunit.testutil.TestUtils;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  /**
43   * @author Manuel Laflamme
44   * @version $Revision$
45   * @since Feb 18, 2002
46   */
47  public class DatabaseEnvironment
48  {
49      private static final String DBUNIT_PROPERTIES_FILENAME =
50              "dbunit.properties";
51  
52      private static final Logger logger =
53              LoggerFactory.getLogger(DatabaseEnvironment.class);
54  
55      private static DatabaseEnvironment INSTANCE = null;
56  
57      private DatabaseProfile _profile = null;
58      private IDatabaseConnection _connection = null;
59      private IDataSet _dataSet = null;
60      private IDatabaseTester _databaseTester = null;
61  
62      /**
63       * Optional "dbunit.properties" is loaded if present and merged with System
64       * properties and the whole set is returned.
65       * <p>
66       * If absent (which is the normal scenario), only System properties are
67       * returned.
68       * <p>
69       * "dbunit.properties" is useful for environment which make it difficult if
70       * not impossible to use Maven's profiles. Example is IntelliJ IDEA which
71       * when calling Junit tests, bypass Maven completely. Since profiles are not
72       * used, database configuration is not properly set and tests fail.
73       * "dbunit.properties" contains the missing properties which a profile would
74       * set.
75       * <p>
76       * Following is an example of the content of "dbunit.properties":
77       * <p>
78       * DATABASE_PROFILE=h2 dbunit.profile.driverClass=org.hsqldb.jdbcDriver
79       * dbunit.profile.url=jdbc:hsqldb:mem:.
80       * <p>
81       * Simply create "dbunit.properties" under "src/test/resources".
82       *
83       * @return Merged DbUnit and System properties.
84       * @throws IOException
85       *             Thrown if an error occurs when attempting to read
86       *             "dbunit.properties".
87       */
88      protected static Properties getProperties() throws IOException
89      {
90          final Properties properties = System.getProperties();
91  
92          final InputStream inputStream =
93                  DatabaseEnvironment.class.getClassLoader()
94                          .getResourceAsStream(DBUNIT_PROPERTIES_FILENAME);
95          if (inputStream != null)
96          {
97              logger.info("Loaded properties from file '{}'",
98                      DBUNIT_PROPERTIES_FILENAME);
99              properties.load(inputStream);
100             inputStream.close();
101         }
102 
103         return properties;
104     }
105 
106     public static DatabaseEnvironment getInstance() throws Exception
107     {
108         if (INSTANCE == null)
109         {
110             final DatabaseProfile profile =
111                     new DatabaseProfile(getProperties());
112 
113             final String profileName = profile.getActiveProfile();
114             if (profileName == null || profileName.equals("hsqldb"))
115             {
116                 INSTANCE = new HypersonicEnvironment(profile);
117             } else if (profileName.equals("oracle"))
118             {
119                 INSTANCE = new OracleEnvironment(profile);
120             } else if (profileName.equals("oracle10"))
121             {
122                 INSTANCE = new Oracle10Environment(profile);
123             } else if (profileName.equals("postgresql"))
124             {
125                 INSTANCE = new PostgresqlEnvironment(profile);
126             } else if (profileName.equals("mysql"))
127             {
128                 INSTANCE = new MySqlEnvironment(profile);
129             } else if (profileName.equals("derby"))
130             {
131                 INSTANCE = new DerbyEnvironment(profile);
132             } else if (profileName.equals("h2"))
133             {
134                 INSTANCE = new H2Environment(profile);
135             } else if (profileName.equals("mssql"))
136             {
137                 INSTANCE = new MsSqlEnvironment(profile);
138             } else
139             {
140                 INSTANCE = new DatabaseEnvironment(profile);
141             }
142         }
143 
144         return INSTANCE;
145     }
146 
147     public DatabaseEnvironment(final DatabaseProfile profile,
148             final Callable<Void> preDdlFunction) throws Exception
149     {
150         if (null != preDdlFunction)
151         {
152             preDdlFunction.call();
153         }
154 
155         _profile = profile;
156         final File file = TestUtils.getFile("xml/dataSetTest.xml");
157         _dataSet = new XmlDataSet(new FileReader(file));
158         _databaseTester = new JdbcDatabaseTester(_profile.getDriverClass(),
159                 _profile.getConnectionUrl(), _profile.getUser(),
160                 _profile.getPassword(), _profile.getSchema());
161 
162         DdlExecutor.execute("sql/" + _profile.getProfileDdl(),
163                 getConnection().getConnection(),
164                 profile.getProfileMultilineSupport(), true);
165     }
166 
167     public DatabaseEnvironment(final DatabaseProfile profile) throws Exception
168     {
169         this(profile, null);
170     }
171 
172     public IDatabaseConnection getConnection() throws Exception
173     {
174         // First check if the current connection is still valid and open
175         // The connection may have been closed by a consumer
176         if (_connection != null && _connection.getConnection().isClosed())
177         {
178             // Reset the member so that a new connection will be created
179             _connection = null;
180         }
181 
182         if (_connection == null)
183         {
184             final String name = _profile.getDriverClass();
185             Class.forName(name);
186             final Connection connection =
187                     DriverManager.getConnection(_profile.getConnectionUrl(),
188                             _profile.getUser(), _profile.getPassword());
189             _connection =
190                     new DatabaseConnection(connection, _profile.getSchema());
191         }
192         return _connection;
193     }
194 
195     protected void setupDatabaseConfig(final DatabaseConfig config)
196     {
197         // Override in subclasses as necessary.
198     }
199 
200     public IDatabaseTester getDatabaseTester()
201     {
202         return _databaseTester;
203     }
204 
205     public void closeConnection() throws Exception
206     {
207         if (_connection != null)
208         {
209             _connection.close();
210             _connection = null;
211         }
212     }
213 
214     public IDataSet getInitDataSet() throws Exception
215     {
216         return _dataSet;
217     }
218 
219     public DatabaseProfile getProfile() throws Exception
220     {
221         return _profile;
222     }
223 
224     public boolean support(final TestFeature feature)
225     {
226         final String[] unsupportedFeatures = _profile.getUnsupportedFeatures();
227         for (int i = 0; i < unsupportedFeatures.length; i++)
228         {
229             final String unsupportedFeature = unsupportedFeatures[i];
230             if (feature.toString().equals(unsupportedFeature))
231             {
232                 return false;
233             }
234         }
235 
236         return true;
237     }
238 
239     /**
240      * Returns the string converted as an identifier according to the metadata
241      * rules of the database environment. Most databases convert all metadata
242      * identifiers to uppercase. PostgreSQL converts identifiers to lowercase.
243      * MySQL preserves case.
244      *
245      * @param str
246      *            The identifier.
247      * @return The identifier converted according to database rules.
248      */
249     public String convertString(final String str)
250     {
251         return str == null ? null : str.toUpperCase();
252     }
253 
254     @Override
255     public String toString()
256     {
257         final StringBuffer sb = new StringBuffer();
258         sb.append(getClass().getName()).append("[");
259         sb.append("_profile=").append(_profile);
260         sb.append(", _connection=").append(_connection);
261         sb.append(", _dataSet=").append(_dataSet);
262         sb.append(", _databaseTester=").append(_databaseTester);
263         sb.append("]");
264         return sb.toString();
265     }
266 }