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.database;
23  
24  import java.sql.Connection;
25  import java.sql.SQLException;
26  
27  import org.dbunit.DatabaseUnitException;
28  import org.dbunit.util.SQLHelper;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   * This class adapts a JDBC <code>Connection</code> to a
34   * {@link IDatabaseConnection}.
35   *
36   * @author Manuel Laflamme
37   * @version $Revision$
38   * @since Feb 21, 2002
39   */
40  public class DatabaseConnection extends AbstractDatabaseConnection
41          implements IDatabaseConnection
42  {
43  
44      /**
45       * Logger for this class
46       */
47      private static final Logger logger = LoggerFactory.getLogger(DatabaseConnection.class);
48  
49      private final Connection _connection;
50      private final String _schema;
51  
52      /**
53       * Creates a new <code>DatabaseConnection</code>.
54       *
55       * @param connection the adapted JDBC connection
56       * @throws DatabaseUnitException
57       */
58      public DatabaseConnection(Connection connection) throws DatabaseUnitException
59      {
60        this( connection, null );
61      }
62  
63      /**
64       * Creates a new <code>DatabaseConnection</code> using a specific schema.
65       *
66       * @param connection the adapted JDBC connection
67       * @param schema the database schema. Note that the schema name is case sensitive. This
68       * is necessary because schemas with the same name but different case can coexist on one
69       * database. <br>
70       * Here an example that creates two users/schemas for oracle where only the case is different:<br>
71       * <code>
72       * create user dbunittest identified by dbunittest;
73       * create user "dbunittest" identified by "dbunittest";
74       * </code>
75       * The first one creates the "default" user where everything is interpreted by oracle in uppercase.
76       * The second one is completely lowercase because of the quotes.
77       * @throws DatabaseUnitException 
78       */
79      public DatabaseConnection(Connection connection, String schema) throws DatabaseUnitException
80      {
81      	this(connection, schema, false);
82      }
83  
84      /**
85       * Creates a new <code>DatabaseConnection</code> using a specific schema.
86       *
87       * @param connection the adapted JDBC connection
88       * @param schema the database schema. Note that the schema name is case sensitive. This
89       * is necessary because schemas with the same name but different case can coexist on one
90       * database. <br>
91       * Here an example that creates two users/schemas for oracle where only the case is different:<br>
92       * <code>
93       * create user dbunittest identified by dbunittest;
94       * create user "dbunittest" identified by "dbunittest";
95       * </code>
96       * The first one creates the "default" user where everything is interpreted by oracle in uppercase.
97       * The second one is completely lowercase because of the quotes.
98       * @param validate If <code>true</code> an exception is thrown when the given schema
99       * does not exist according to the DatabaseMetaData. If <code>false</code> the validation
100      * will only print a warning if the schema was not found.
101      * @since 2.3.0
102      * @throws DatabaseUnitException If the <code>validate</code> parameter is <code>true</code> and the 
103      * validation of the given connection/schema was not successful (added with 2.3.0). This can happen if the given
104      * schema does not exist or if the jdbc driver does not implement the metaData.getSchemas() method properly.
105      */
106     public DatabaseConnection(Connection connection, String schema, boolean validate) throws DatabaseUnitException
107     {
108         if(connection == null)
109         {
110             throw new NullPointerException("The parameter 'connection' must not be null");
111         }
112         _connection = connection;
113         
114         if(schema != null)
115         {
116             _schema = SQLHelper.correctCase(schema, connection);
117             SQLHelper.logInfoIfValueChanged(schema, _schema, "Corrected schema name:", DatabaseConnection.class);
118         }
119         else
120         {
121             _schema = null;
122         }
123 
124         printConnectionInfo();
125         validateSchema(validate);
126     }
127 
128 	////////////////////////////////////////////////////////////////////////////
129     // IDatabaseConnection interface
130 
131     public Connection getConnection() throws SQLException
132     {
133         return _connection;
134     }
135 
136     public String getSchema()
137     {
138         return _schema;
139     }
140 
141     public void close() throws SQLException
142     {
143         logger.debug("close() - start");
144         _connection.close();
145     }
146     
147     
148     /**
149      * Prints debugging information about the current JDBC connection
150      */
151     private void printConnectionInfo() 
152     {
153     	if(logger.isDebugEnabled()) 
154     	{
155         	try {
156     			logger.debug("Database connection info: " + SQLHelper.getDatabaseInfo(_connection.getMetaData()));
157     		} 
158         	catch (SQLException e) {
159     			logger.warn("Exception while trying to retrieve database info from connection", e);
160     		}
161     	}
162 	}
163 
164     /**
165      * Validates if the database schema exists for this connection.
166      * @param validateStrict If <code>true</code> an exception is thrown when the given schema
167      * does not exist according to the DatabaseMetaData. If <code>false</code> the validation
168      * will only print a warning if the schema was not found.
169      * @throws DatabaseUnitException
170      */
171     private void validateSchema(boolean validateStrict) throws DatabaseUnitException
172     {
173     	if(logger.isDebugEnabled())
174     		logger.debug("validateSchema(validateStrict={}) - start", String.valueOf(validateStrict));
175         
176         if(this._schema == null)
177         {
178             logger.debug("Schema is null. Nothing to validate.");
179             return;
180         }
181         
182         try
183         {
184             boolean schemaExists = SQLHelper.schemaExists(this._connection, this._schema);
185             if(!schemaExists)
186             {
187             	// Under certain circumstances the cause might be that the JDBC driver
188 				// implementation of 'DatabaseMetaData.getSchemas()' is not correct 
189             	// (known issue of MySQL driver).
190             	String msg = "The given schema '" + this._schema + "' does not exist.";
191             	// If strict validation is wished throw an exception
192             	if(validateStrict)
193             		throw new DatabaseUnitException(msg);
194             	else
195             		logger.warn(msg);
196             }
197         }
198         catch(SQLException e)
199         {
200             throw new DatabaseUnitException("Exception while checking the schema for validity", e);
201         }
202     }
203     
204     public String toString()
205     {
206         StringBuffer sb = new StringBuffer();
207         sb.append(getClass().getName()).append("[");
208         sb.append("schema=").append(_schema);
209         sb.append(", connection=").append(_connection);
210         sb.append(", super=").append(super.toString());
211         sb.append("]");
212         return sb.toString();
213     }
214 }