code style improvements.
[utils] / test / enterprise / src / main / java / org / wamblee / test / persistence / DatabaseBuilder.java
1 /*
2  * Copyright 2005-2010 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */ 
16 package org.wamblee.test.persistence;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.ServiceLoader;
22 import java.util.logging.Logger;
23
24 /**
25  * DatabaseBuilder is used from unit test to obtain a reference to a database
26  * from unit test. This database is either an inmemory database or represents an
27  * external database. Purpose of this utility is to make test code independent
28  * of the particular database used and specifically to be able to run database
29  * tests without any configuration at all (using an inmemory database).
30  * 
31  * The type of database to use can be overridden by specifying either a system
32  * property or an environment variable ({@link #DB_CAPABILITIES_PROP}) that
33  * contains the comma-separated capabilities of the database. Each database type
34  * provides its own capabilities (see {@link DatabaseProvider} implementations}.
35  * 
36  * 
37  * There are currently two database types available:
38  * <ul>
39  * <li>Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This
40  * is the default.</li>
41  * <li>External: An arbitrary external database configured using system
42  * properties or environment variables in the usual way using a JDBC URL,
43  * username, and password.</li>
44  * </ul>
45  * 
46  * The <code>DatabaseBuilder</code> uses the {@link ServiceLoader} mechanism to
47  * find implementations of {@link DatabaseProvider} on the classpath. In the
48  * {@link #getDatabase(String...)} method a number of capabilities are passed.
49  * The database providers are then searched in (arbitrary) order and the first
50  * one that has all required capabilities is returned.
51  * 
52  * {@link #getSupportedDatabases()} gives a list of all available databases.
53  */
54 public class DatabaseBuilder {
55
56     private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class
57         .getName());
58
59     /**
60      * Environmment variable by which capabilities of the requested database can
61      * be defined
62      */
63     public static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES";
64
65     private static ServiceLoader<DatabaseProvider> LOADER = 
66         ServiceLoader.load(DatabaseProvider.class);
67
68     /**
69      * Constructs the database builder. 
70      */
71     private DatabaseBuilder() {
72         // Empty.
73     }
74
75     private static String[] parseCapabilities(String aValue) {
76         return aValue.split(",");
77     }
78
79     /**
80      * Gets the first database that has all required capabilities.
81      * 
82      * @param aCapabilities
83      *            Capabilities.
84      * @return Database to use.
85      */
86     public static Database getDatabase(String... aCapabilities) {
87         if (aCapabilities.length == 0) {
88             LOGGER.info("Examining database capabilities");
89             LOGGER.info("  Checking system property " + DB_CAPABILITIES_PROP);
90             String capabilities = System.getProperty(DB_CAPABILITIES_PROP);
91             if (capabilities != null) {
92                 aCapabilities = parseCapabilities(capabilities);
93             } else {
94                 LOGGER.info("  Checking environment variable " +
95                     DB_CAPABILITIES_PROP);
96                 capabilities = System.getenv(DB_CAPABILITIES_PROP);
97                 if (capabilities != null) {
98                     aCapabilities = parseCapabilities(capabilities);
99                 } else {
100                     LOGGER.info("  Using default capabilities");
101                     aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY };
102                 }
103             }
104             LOGGER.info("Using capabilities: " + Arrays.asList(aCapabilities));
105         }
106         synchronized (DatabaseBuilder.class) {
107             for (DatabaseProvider db : LOADER) {
108                 if (db.supportsCapabilities(aCapabilities)) {
109                     return db.create();
110                 }
111             }
112         }
113         throw new RuntimeException(
114             "No database found that satisfies capabilities: " +
115                 Arrays.asList(aCapabilities));
116     }
117
118     /**
119      * Gets a list of available databases.
120      * 
121      * @return List of databases.
122      */
123     public static List<DatabaseDescription> getSupportedDatabases() {
124         List<DatabaseDescription> descriptions = new ArrayList<DatabaseDescription>();
125         for (DatabaseProvider db : LOADER) {
126             descriptions.add(db.getDescription());
127         }
128         return descriptions;
129     }
130
131 }