001: package liquibase.test;
002:
003: import liquibase.database.Database;
004: import liquibase.database.DatabaseConnection;
005: import liquibase.database.DatabaseFactory;
006: import liquibase.exception.JDBCException;
007:
008: import java.sql.Connection;
009: import java.sql.Driver;
010: import java.sql.SQLException;
011: import java.util.*;
012:
013: /**
014: * Controls the database connections for running tests.
015: * For times we aren't wanting to run the database-hitting tests, set the "test.databases" system property
016: * to be a comma-separated list of the databses we want to test against. The string is checked against the database url.
017: */
018: public class TestContext {
019: private static TestContext instance = new TestContext();
020:
021: private Set<Database> availableDatabases = new HashSet<Database>();
022: private Set<Database> allDatabases;
023: private Set<DatabaseConnection> availableConnections;
024:
025: private final String[] DEFAULT_TEST_URLS = new String[] {
026: "jdbc:Cache://127.0.0.1:1972/liquibase",
027: "jdbc:db2://localhost:50000/liquibas",
028: // "jdbc:derby:liquibase;create=true",
029: "jdbc:firebirdsql:localhost/3050:c:\\firebird\\liquibase.fdb",
030: "jdbc:h2:mem:liquibase",
031: "jdbc:hsqldb:mem:liquibase",
032: "jdbc:jtds:sqlserver://localhost;databaseName=liquibase",
033: // "jdbc:sqlserver://localhost;databaseName=liquibase",
034: "jdbc:mysql://localhost/liquibase",
035: "jdbc:oracle:thin:@localhost/XE",
036: "jdbc:postgresql://localhost/liquibase",
037: // "jdbc:jtds:sybase://localhost/nathan:5000",
038: // "jdbc:sybase:Tds:"+ InetAddress.getLocalHost().getHostName()+":5000/liquibase",
039: "jdbc:sapdb://localhost/liquibas", };
040:
041: private Map<String, DatabaseConnection> connectionsByUrl = new HashMap<String, DatabaseConnection>();
042: private Map<String, Boolean> connectionsAttempted = new HashMap<String, Boolean>();
043: public static final String ALT_SCHEMA = "LIQUIBASEB";
044: public static final String ALT_TABLESPACE = "LIQUIBASE2";
045: private static final String TEST_DATABASES_PROPERTY = "test.databases";
046:
047: private DatabaseConnection openConnection(final String url)
048: throws Exception {
049: if (connectionsAttempted.containsKey(url)) {
050: return connectionsByUrl.get(url);
051: }
052: connectionsAttempted.put(url, Boolean.TRUE);
053:
054: if (System.getProperty(TEST_DATABASES_PROPERTY) != null) {
055: boolean shouldTest = false;
056: String[] databasesToTest = System.getProperty(
057: TEST_DATABASES_PROPERTY).split("\\s*,\\s*");
058: for (String database : databasesToTest) {
059: if (url.indexOf(database) >= 0) {
060: shouldTest = true;
061: }
062: }
063: if (!shouldTest) {
064: System.out
065: .println("test.databases system property forbids testing against "
066: + url);
067: return null;
068: }
069: }
070:
071: String username = getUsername(url);
072: String password = getPassword(url);
073:
074: JUnitJDBCDriverClassLoader jdbcDriverLoader = JUnitJDBCDriverClassLoader
075: .getInstance();
076: final Driver driver = (Driver) Class.forName(
077: DatabaseFactory.getInstance().findDefaultDriver(url),
078: true, jdbcDriverLoader).newInstance();
079:
080: Properties info = new Properties();
081: info.put("user", username);
082: if (password != null) {
083: info.put("password", password);
084: }
085:
086: Connection connection;
087: try {
088: connection = driver.connect(url, info);
089: } catch (SQLException e) {
090: System.out.println("Could not connect to " + url
091: + ": Will not test against");
092: return null; //could not connect
093: }
094: if (connection == null) {
095: throw new JDBCException(
096: "Connection could not be created to "
097: + url
098: + " with driver "
099: + driver.getClass().getName()
100: + ". Possibly the wrong driver for the given database URL");
101: }
102:
103: Database database = DatabaseFactory.getInstance()
104: .findCorrectDatabaseImplementation(connection);
105: final DatabaseConnection databaseConnection = database
106: .getConnection();
107:
108: databaseConnection.setAutoCommit(false);
109:
110: try {
111: if (url.startsWith("jdbc:hsql")) {
112: databaseConnection.createStatement().execute(
113: "CREATE SCHEMA " + ALT_SCHEMA
114: + " AUTHORIZATION DBA");
115: } else if (url.startsWith("jdbc:sqlserver")
116: || url.startsWith("jdbc:postgresql")
117: || url.startsWith("jdbc:h2")) {
118: databaseConnection.createStatement().execute(
119: "CREATE SCHEMA " + ALT_SCHEMA);
120: }
121: if (!databaseConnection.getAutoCommit()) {
122: databaseConnection.commit();
123: }
124: } catch (SQLException e) {
125: // e.printStackTrace();
126: ; //schema already exists
127: } finally {
128: databaseConnection.rollback();
129: }
130:
131: connectionsByUrl.put(url, databaseConnection);
132:
133: Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
134:
135: public void run() {
136: try {
137: try {
138: if (!databaseConnection.getAutoCommit()) {
139: databaseConnection.rollback();
140: }
141: } catch (SQLException e) {
142: ;
143: }
144:
145: databaseConnection.close();
146: } catch (SQLException e) {
147: System.out.println("Could not close " + url);
148: e.printStackTrace();
149: }
150: }
151: }));
152:
153: return databaseConnection;
154: }
155:
156: private String getUsername(String url) {
157: if (url.startsWith("jdbc:hsqldb")) {
158: return "sa";
159: }
160: return "liquibase";
161: }
162:
163: private String getPassword(String url) {
164: if (url.startsWith("jdbc:hsqldb")) {
165: return "";
166: }
167: return "liquibase";
168: }
169:
170: public static TestContext getInstance() {
171: return instance;
172: }
173:
174: public String[] getTestUrls() {
175: return DEFAULT_TEST_URLS;
176: }
177:
178: public Set<Database> getAllDatabases() {
179: if (allDatabases == null) {
180: allDatabases = new HashSet<Database>();
181:
182: allDatabases.addAll(DatabaseFactory.getInstance()
183: .getImplementedDatabases());
184:
185: }
186: return allDatabases;
187: }
188:
189: public Set<Database> getAvailableDatabases() throws Exception {
190: if (availableDatabases.size() == 0) {
191: for (DatabaseConnection conn : getAvailableConnections()) {
192: availableDatabases.add(DatabaseFactory.getInstance()
193: .findCorrectDatabaseImplementation(conn));
194: }
195: }
196: return availableDatabases;
197: }
198:
199: public Set<DatabaseConnection> getAvailableConnections()
200: throws Exception {
201: if (availableConnections == null) {
202: availableConnections = new HashSet<DatabaseConnection>();
203: for (String url : getTestUrls()) {
204: // if (url.indexOf("jtds") >= 0) {
205: // continue;
206: // }
207: DatabaseConnection connection = openConnection(url);
208: if (connection != null) {
209: availableConnections.add(connection);
210: }
211: }
212: }
213:
214: return availableConnections;
215: }
216:
217: public DatabaseConnection getConnection(String url)
218: throws Exception {
219: return openConnection(url);
220: }
221:
222: public String getTestUrl(Database database) {
223: for (String url : getTestUrls()) {
224: if (database.getDefaultDriver(url) != null) {
225: return url;
226: }
227: }
228: throw new RuntimeException("Could not find url for " + database);
229: }
230: }
|