1 package org.wamblee.support.persistence;
3 import java.util.ArrayList;
4 import java.util.Arrays;
6 import java.util.ServiceLoader;
7 import java.util.logging.Logger;
10 * DatabaseBuilder is used from unit test to obtain a reference to a database
11 * from unit test. This database is either an inmemory database or represents an
12 * external database. Purpose of this utility is to make test code independent
13 * of the particular database used and specifically to be able to run database
14 * tests without any configuration at all (using an inmemory database).
16 * The type of database to use can be overridden by specifying either a system
17 * property or an environment variable ({@link #DB_CAPABILITIES_PROP}) that
18 * contains the comma-separated capabilities of the database. Each database type
19 * provides its own capabilities (see {@link DatabaseProvider} implementations}.
22 * There are currently two database types available:
24 * <li>Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This
25 * is the default.</li>
26 * <li>External: An arbitrary external database configured using system
27 * properties or environment variables in the usual way using a JDBC URL,
28 * username, and password.</li>
31 * The <code>DatabaseBuilder</code> uses the {@link ServiceLoader} mechanism to
32 * find implementations of {@link DatabaseProvider} on the classpath. In the
33 * {@link #getDatabase(String...)} method a number of capabilities are passed.
34 * The database providers are then searched in (arbitrary) order and the first
35 * one that has all required capabilities is returned.
37 * {@link #getSupportedDatabases()} gives a list of all available databases.
39 public class DatabaseBuilder {
41 private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class
45 * Environmment variable by which capabilities of the requested database can
48 private static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES";
50 private static ServiceLoader<DatabaseProvider> LOADER = null;
52 private DatabaseBuilder() {
56 private static String[] parseCapabilities(String aValue) {
57 return aValue.split(",");
61 * Gets the first database that has all required capabilities.
63 * @param aCapabilities
65 * @return Database to use.
67 public static Database getDatabase(String... aCapabilities) {
68 if (aCapabilities.length == 0) {
69 LOGGER.info("Examining database capabilities");
70 LOGGER.info(" Checking system property " + DB_CAPABILITIES_PROP);
71 String capabilities = System.getProperty(DB_CAPABILITIES_PROP);
72 if (capabilities != null) {
73 aCapabilities = parseCapabilities(capabilities);
75 LOGGER.info(" Checking environment variable " +
76 DB_CAPABILITIES_PROP);
77 capabilities = System.getenv(DB_CAPABILITIES_PROP);
78 if (capabilities != null) {
79 aCapabilities = parseCapabilities(capabilities);
81 LOGGER.info(" Using default capabilities");
82 aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY };
85 LOGGER.info("Using capabilities: " + aCapabilities);
87 synchronized (DatabaseBuilder.class) {
89 for (DatabaseProvider db : LOADER) {
90 if (db.supportsCapabilities(aCapabilities)) {
95 throw new RuntimeException(
96 "No database found that satisfies capabilities: " +
97 Arrays.asList(aCapabilities));
101 * Gets a list of available databases.
103 * @return List of databases.
105 public static List<DatabaseDescription> getSupportedDatabases() {
107 List<DatabaseDescription> descriptions = new ArrayList<DatabaseDescription>();
108 for (DatabaseProvider db : LOADER) {
109 descriptions.add(db.getDescription());
114 private static void initLoader() {
115 if (LOADER == null) {
116 LOADER = ServiceLoader.load(DatabaseProvider.class);