9c599a0a75cddf8f81203b217aeb76885827a5e4
[utils] / test / enterprise / src / main / java / org / wamblee / support / persistence / DatabaseBuilder.java
1 package org.wamblee.support.persistence;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6 import java.util.ServiceLoader;
7 import java.util.logging.Logger;
8
9 /**
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 of the 
13  * particular database used and specifically to be able to run database tests without 
14  * any configuration at all (using an inmemory database).  
15  * 
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}.
20  * 
21  * 
22  * There are currently two database types available: 
23  * <ul>
24  *   <li> Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This is the default. 
25  *   </li>
26  *   <li> External: An arbitrary external database configured using system properties or environment variables
27  *     in the usual way using a JDBC URL, username, and password. 
28  *   </li>
29  * </ul>
30  * 
31  * The <code>DatabaseBuilder</code> uses the {@link ServiceLoader} mechanism to find implementations
32  * of {@link DatabaseProvider} on the classpath. In the {@link #getDatabase(String...)} method a number of 
33  * capabilities are passed. The database providers are then searched in (arbitrary) order and the first one that
34  * has all required capabilities is returned. 
35  * 
36  * {@link #getSupportedDatabases()} gives a list of all available databases. 
37  */
38 public class DatabaseBuilder {
39
40         private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class
41                         .getName());
42
43         /**
44          * Environmment variable by which capabilities of the requested database can
45          * be defined
46          */
47         private static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES";
48
49         private static ServiceLoader<DatabaseProvider> LOADER = null;
50
51         private DatabaseBuilder() {
52                 // Empty.
53         }
54
55         private static String[] parseCapabilities(String aValue) {
56                 return aValue.split(",");
57         }
58
59         /**
60          * Gets the first database that has all required capabilities. 
61          * @param aCapabilities Capabilities. 
62          * @return Database to use. 
63          */
64         public static Database getDatabase(String... aCapabilities) {
65                 if (aCapabilities.length == 0) {
66                         LOGGER.info("Examining database capabilities");
67                         LOGGER.info("  Checking system property " + DB_CAPABILITIES_PROP);
68                         String capabilities = System.getProperty(DB_CAPABILITIES_PROP);
69                         if (capabilities != null) {
70                                 aCapabilities = parseCapabilities(capabilities);
71                         } else {
72                                 LOGGER.info("  Checking environment variable "
73                                                 + DB_CAPABILITIES_PROP);
74                                 capabilities = System.getenv(DB_CAPABILITIES_PROP);
75                                 if (capabilities != null) {
76                                         aCapabilities = parseCapabilities(capabilities);
77                                 } else {
78                                         LOGGER.info("  Using default capabilities");
79                                         aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY };
80                                 }
81                         }
82                         LOGGER.info("Using capabilities: " + aCapabilities);
83                 }
84                 synchronized (DatabaseBuilder.class) {
85                         initLoader();
86                         for (DatabaseProvider db : LOADER) {
87                                 if (db.supportsCapabilities(aCapabilities)) {
88                                         return db.create();
89                                 }
90                         }
91                 }
92                 throw new RuntimeException(
93                                 "No database found that satisfies capabilities: "
94                                                 + Arrays.asList(aCapabilities));
95         }
96
97         /**
98          * Gets a list of available databases. 
99          * @return List of databases. 
100          */
101         public static List<DatabaseDescription> getSupportedDatabases() {
102                 initLoader();
103                 List<DatabaseDescription> descriptions = new ArrayList<DatabaseDescription>();
104                 for (DatabaseProvider db : LOADER) {
105                         descriptions.add(db.getDescription());
106                 }
107                 return descriptions;
108         }
109
110         private static void initLoader() {
111                 if (LOADER == null) {
112                         LOADER = ServiceLoader.load(DatabaseProvider.class);
113                 }
114         }
115
116 }