Moved database-utils utilities herein.
This is a find home for them, and it allows the miniscule database-utils to go away.
This commit is contained in:
@@ -58,6 +58,12 @@
|
|||||||
<version>2.5</version>
|
<version>2.5</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>8.3-606.jdbc4</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// ooo-util - a place for OOO utilities
|
||||||
|
// Copyright (C) 2011 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://github.com/threerings/ooo-util/blob/master/LICENSE
|
||||||
|
|
||||||
|
package com.threerings.util;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import com.samskivert.util.Config;
|
||||||
|
|
||||||
|
import com.samskivert.jdbc.ConnectionProvider;
|
||||||
|
import com.samskivert.jdbc.StaticConnectionProvider;
|
||||||
|
|
||||||
|
public class ConnectionProviderUtil
|
||||||
|
{
|
||||||
|
public enum DB {
|
||||||
|
postgres, hsqldb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ConnectionProvider for the type of databases specified by <code>db.type</code> in
|
||||||
|
* <code>config</code>.
|
||||||
|
* <h2>Types</h2>
|
||||||
|
* <dl>
|
||||||
|
* <dt>postgres</dt>
|
||||||
|
* <dd>Uses {@link PostgresUtil#createPoolingProvider(Config, String)} with the given config
|
||||||
|
* and ident.</dd>
|
||||||
|
* <dt>hsqldb</dt>
|
||||||
|
* <dd>a {@link StaticConnectionProvider} is created from
|
||||||
|
* the sub-properties under <code>db</code>. It defaults to an in-memory database if
|
||||||
|
* <code>db.default.url</code> isn't defined.
|
||||||
|
* </dd>
|
||||||
|
* </dl>
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException - if <code>db.type</code> doesn't match a known type.
|
||||||
|
*/
|
||||||
|
public static ConnectionProvider createProvider (Config config, String ident)
|
||||||
|
{
|
||||||
|
return createProvider(config, ident, "db");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ConnectionProvider as in {@link #createProvider(Config,String)}, but uses
|
||||||
|
* the supplied {@code prefix} in place of {@code db}.
|
||||||
|
*/
|
||||||
|
public static ConnectionProvider createProvider (Config config, String ident, String prefix)
|
||||||
|
{
|
||||||
|
DB type = DB.valueOf(config.getValue(prefix + ".type", "postgres"));
|
||||||
|
switch(type) {
|
||||||
|
case postgres:
|
||||||
|
return PostgresUtil.createPoolingProvider(config, ident, prefix);
|
||||||
|
case hsqldb:
|
||||||
|
Properties sub = config.getSubProperties(prefix);
|
||||||
|
putIfNotPresent(sub, "default.driver", "org.hsqldb.jdbcDriver");
|
||||||
|
putIfNotPresent(sub, "default.url", "jdbc:hsqldb:mem:.");
|
||||||
|
putIfNotPresent(sub, "default.username", "sa");
|
||||||
|
putIfNotPresent(sub, "default.password", "");
|
||||||
|
return new StaticConnectionProvider(sub);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown db type " +
|
||||||
|
config.getValue(prefix + ".type", (String)null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void putIfNotPresent (Properties props, String key, String value)
|
||||||
|
{
|
||||||
|
if (!props.containsKey(key)) {
|
||||||
|
props.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
//
|
||||||
|
// ooo-util - a place for OOO utilities
|
||||||
|
// Copyright (C) 2011 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://github.com/threerings/ooo-util/blob/master/LICENSE
|
||||||
|
|
||||||
|
package com.threerings.util;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.postgresql.jdbc2.optional.PoolingDataSource;
|
||||||
|
|
||||||
|
import com.samskivert.jdbc.ConnectionProvider;
|
||||||
|
import com.samskivert.jdbc.DataSourceConnectionProvider;
|
||||||
|
import com.samskivert.util.Config;
|
||||||
|
import com.samskivert.util.MissingPropertyException;
|
||||||
|
|
||||||
|
import static com.samskivert.util.PropertiesUtil.requireProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Postgres related utility methods.
|
||||||
|
*/
|
||||||
|
public class PostgresUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a ConnectionProvider that communicates with a Postgres database server using
|
||||||
|
* read-only and read-write connections via a connection pooled data source. The supplied
|
||||||
|
* config must provide the following configuration:
|
||||||
|
* <pre>
|
||||||
|
* db.default.server = DBHOST
|
||||||
|
* db.default.port = 5432
|
||||||
|
* db.default.database = DATABASE
|
||||||
|
* db.default.username = USERNAME
|
||||||
|
* db.default.password = PASSWORD
|
||||||
|
* db.readonly.maxconns = 1
|
||||||
|
* db.readwrite.maxconns = 1
|
||||||
|
* </pre>
|
||||||
|
* It can optionally provide overrides for the server, port, database, username and password
|
||||||
|
* fields for the readonly and readwrite conncetions:
|
||||||
|
* <pre>
|
||||||
|
* db.readonly.server = READSLAVE
|
||||||
|
* db.readonly.username = READUSER
|
||||||
|
* db.readonly.password = READPASS
|
||||||
|
* db.readwrite.server = MASTER
|
||||||
|
* ...
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param config used to obtain the configuration data.
|
||||||
|
* @param projectId a unique identifier for the system creating this provider which will be
|
||||||
|
* used to prefix the identifiers of the data source names (which are JVM global).
|
||||||
|
*/
|
||||||
|
public static ConnectionProvider createPoolingProvider (Config config, String projectId)
|
||||||
|
{
|
||||||
|
return createPoolingProvider(config, projectId, "db");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ConnectionProvider as in {@link #createPoolingProvider(Config,String)}, but uses
|
||||||
|
* the supplied {@code prefix} in place of {@code db}.
|
||||||
|
*/
|
||||||
|
public static ConnectionProvider createPoolingProvider (
|
||||||
|
Config config, String projectId, String prefix)
|
||||||
|
{
|
||||||
|
final DataSource[] sources = new DataSource[2];
|
||||||
|
String[] modes = new String[] { "readonly", "readwrite" };
|
||||||
|
String defPrefix = prefix + ".default";
|
||||||
|
for (int ii = 0; ii < sources.length; ii++) {
|
||||||
|
String modePrefix = prefix + "." + modes[ii];
|
||||||
|
try {
|
||||||
|
// start with defaults, then apply overrides
|
||||||
|
Properties props = config.getSubProperties(defPrefix);
|
||||||
|
config.getSubProperties(modePrefix, props);
|
||||||
|
PoolingDataSource source = new PoolingDataSource();
|
||||||
|
source.setDataSourceName(projectId + "." + modes[ii]);
|
||||||
|
source.setServerName(requireProperty(props, "server"));
|
||||||
|
source.setDatabaseName(requireProperty(props, "database"));
|
||||||
|
source.setPortNumber(Integer.parseInt(requireProperty(props, "port")));
|
||||||
|
source.setUser(requireProperty(props, "username"));
|
||||||
|
source.setPassword(requireProperty(props, "password"));
|
||||||
|
source.setMaxConnections(Integer.parseInt(props.getProperty("maxconns", "1")));
|
||||||
|
sources[ii] = source;
|
||||||
|
} catch (MissingPropertyException mpe) {
|
||||||
|
String key = mpe.getKey();
|
||||||
|
throw new MissingPropertyException(
|
||||||
|
key, "Unable to locate required property '" + key + "' as '" +
|
||||||
|
defPrefix + "." + key + "' or '" + modePrefix + "." + key + "'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new DataSourceConnectionProvider("jdbc:postgresql", sources[0], sources[1]) {
|
||||||
|
@Override public void shutdown () {
|
||||||
|
if (_shutdown.getAndSet(true)) {
|
||||||
|
// Only shutdown the sources once; Postgres' pooling data source doesn't like
|
||||||
|
// multiple shutdown calls
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (DataSource source : sources) {
|
||||||
|
((PoolingDataSource)source).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected AtomicBoolean _shutdown = new AtomicBoolean();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user