/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.monitor.hib;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.io.IOUtils;
import org.geoserver.config.GeoServerDataDirectory;
import org.geoserver.monitor.Monitor;
import org.geoserver.monitor.MonitorConfig;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
import org.geotools.util.logging.Logging;
import org.springframework.beans.factory.DisposableBean;
public class MonitoringDataSource extends BasicDataSource implements DisposableBean {
static Logger LOGGER = Logging.getLogger(Monitor.class);
MonitorConfig config;
GeoServerDataDirectory dataDirectory;
public void setConfig(MonitorConfig config) {
this.config = config;
}
public void setDataDirectory(GeoServerDataDirectory dataDir) {
this.dataDirectory = dataDir;
}
@Override
public Connection getConnection() throws SQLException {
try {
if(getDriverClassName() == null) {
synchronized(this) {
if (getDriverClassName() == null) {
initializeDataSource();
}
}
}
return super.getConnection();
}
catch(Exception e) {
//LOGGER.log(Level.WARNING, "Database connection error", e);
config.setError(e);
config.setEnabled(false);
if (e instanceof SQLException) {
throw (SQLException) e;
}
throw (SQLException) new SQLException().initCause(e);
}
}
void initializeDataSource() throws Exception {
Resource monitoringDir = dataDirectory.get("monitoring");
Resource dbprops = monitoringDir.get("db.properties");
if (Resources.exists(dbprops)) {
LOGGER.info("Configuring monitoring database from: " + dbprops.path());
//attempt to configure
try {
configureDataSource(dbprops, monitoringDir);
}
catch(SQLException e) {
//configure failed, try db1.properties
dbprops = monitoringDir.get("db1.properties");
if (Resources.exists(dbprops)) {
try {
configureDataSource(dbprops, monitoringDir);
//secondary file worked, return
return;
}
catch(SQLException e1) {
//secondary file failed as well, try for third
dbprops = monitoringDir.get("db2.properties");
if (Resources.exists(dbprops)) {
try {
configureDataSource(dbprops, monitoringDir);
//third file worked, return
return;
}
catch(SQLException e2) {}
}
}
}
throw e;
}
}
else {
//no db.properties file, use internal default
configureDataSource(null, monitoringDir);
}
}
void configureDataSource(Resource dbprops, Resource monitoringDir) throws Exception {
Properties db = new Properties();
if (dbprops == null) {
dbprops = monitoringDir.get("db.properties");
//use a default, and copy the template over
try (InputStream in = getClass().getResourceAsStream("db.properties"); OutputStream out = dbprops.out()) {
IOUtils.copy(in, out);
}
try (InputStream in = getClass().getResourceAsStream("db.properties")) {
db.load(in);
}
}
else {
try (InputStream in = dbprops.in()) {
db.load(in);
}
}
logDbProperties(db);
//TODO: check for nulls
setDriverClassName(db.getProperty("driver"));
setUrl(getURL(db));
if (db.containsKey("username")) {
setUsername(db.getProperty("username"));
}
if (db.containsKey("password")) {
setPassword(db.getProperty("password"));
}
setDefaultAutoCommit(Boolean.valueOf(db.getProperty("defaultAutoCommit", "true")));
//TODO: make other parameters configurable
setMinIdle(1);
setMaxActive(4);
//test the connection
super.getConnection();
}
void logDbProperties(Properties db) {
if (LOGGER.isLoggable(Level.FINE)) {
StringBuffer sb = new StringBuffer("Monitoring database connection info:\n");
for (Map.Entry e : db.entrySet()) {
sb.append(e.getKey()).append(" = ").append(e.getValue()).append("\n");
}
LOGGER.fine(sb.toString());
}
}
String getURL(Properties db) {
return db.getProperty("url").replace("${GEOSERVER_DATA_DIR}", dataDirectory.root().getAbsolutePath());
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public void destroy() throws Exception {
super.close();
}
}