(no commit message)
[utils] / test / enterprise / src / main / java / org / wamblee / support / persistence / DatabaseBuilder.java
diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java
new file mode 100644 (file)
index 0000000..9c599a0
--- /dev/null
@@ -0,0 +1,116 @@
+package org.wamblee.support.persistence;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.logging.Logger;
+
+/**
+ * DatabaseBuilder is used from unit test to obtain a reference to a database
+ * from unit test. This database is either an inmemory database or represents an
+ * external database. Purpose of this utility is to make test code independent of the 
+ * particular database used and specifically to be able to run database tests without 
+ * any configuration at all (using an inmemory database).  
+ * 
+ * The type of database to use can be overridden by specifying either a system
+ * property or an environment variable ({@link #DB_CAPABILITIES_PROP}) that
+ * contains the comma-separated capabilities of the database. Each database type
+ * provides its own capabilities (see {@link DatabaseProvider} implementations}.
+ * 
+ * 
+ * There are currently two database types available: 
+ * <ul>
+ *   <li> Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This is the default. 
+ *   </li>
+ *   <li> External: An arbitrary external database configured using system properties or environment variables
+ *     in the usual way using a JDBC URL, username, and password. 
+ *   </li>
+ * </ul>
+ * 
+ * The <code>DatabaseBuilder</code> uses the {@link ServiceLoader} mechanism to find implementations
+ * of {@link DatabaseProvider} on the classpath. In the {@link #getDatabase(String...)} method a number of 
+ * capabilities are passed. The database providers are then searched in (arbitrary) order and the first one that
+ * has all required capabilities is returned. 
+ * 
+ * {@link #getSupportedDatabases()} gives a list of all available databases. 
+ */
+public class DatabaseBuilder {
+
+       private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class
+                       .getName());
+
+       /**
+        * Environmment variable by which capabilities of the requested database can
+        * be defined
+        */
+       private static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES";
+
+       private static ServiceLoader<DatabaseProvider> LOADER = null;
+
+       private DatabaseBuilder() {
+               // Empty.
+       }
+
+       private static String[] parseCapabilities(String aValue) {
+               return aValue.split(",");
+       }
+
+       /**
+        * Gets the first database that has all required capabilities. 
+        * @param aCapabilities Capabilities. 
+        * @return Database to use. 
+        */
+       public static Database getDatabase(String... aCapabilities) {
+               if (aCapabilities.length == 0) {
+                       LOGGER.info("Examining database capabilities");
+                       LOGGER.info("  Checking system property " + DB_CAPABILITIES_PROP);
+                       String capabilities = System.getProperty(DB_CAPABILITIES_PROP);
+                       if (capabilities != null) {
+                               aCapabilities = parseCapabilities(capabilities);
+                       } else {
+                               LOGGER.info("  Checking environment variable "
+                                               + DB_CAPABILITIES_PROP);
+                               capabilities = System.getenv(DB_CAPABILITIES_PROP);
+                               if (capabilities != null) {
+                                       aCapabilities = parseCapabilities(capabilities);
+                               } else {
+                                       LOGGER.info("  Using default capabilities");
+                                       aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY };
+                               }
+                       }
+                       LOGGER.info("Using capabilities: " + aCapabilities);
+               }
+               synchronized (DatabaseBuilder.class) {
+                       initLoader();
+                       for (DatabaseProvider db : LOADER) {
+                               if (db.supportsCapabilities(aCapabilities)) {
+                                       return db.create();
+                               }
+                       }
+               }
+               throw new RuntimeException(
+                               "No database found that satisfies capabilities: "
+                                               + Arrays.asList(aCapabilities));
+       }
+
+       /**
+        * Gets a list of available databases. 
+        * @return List of databases. 
+        */
+       public static List<DatabaseDescription> getSupportedDatabases() {
+               initLoader();
+               List<DatabaseDescription> descriptions = new ArrayList<DatabaseDescription>();
+               for (DatabaseProvider db : LOADER) {
+                       descriptions.add(db.getDescription());
+               }
+               return descriptions;
+       }
+
+       private static void initLoader() {
+               if (LOADER == null) {
+                       LOADER = ServiceLoader.load(DatabaseProvider.class);
+               }
+       }
+
+}