Skip to content

Commit

Permalink
Added service for loading database server connection details; this also
Browse files Browse the repository at this point in the history
replaces the need for maintaining database server details in
ords.properties and hibernate.cfg.xml as we can load both user servers
and the metadata server configurations
  • Loading branch information
scottbw committed Apr 30, 2016
1 parent 4d97a0f commit 623eb72
Show file tree
Hide file tree
Showing 11 changed files with 425 additions and 27 deletions.
73 changes: 73 additions & 0 deletions src/main/java/uk/ac/ox/it/ords/security/model/DatabaseServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2015 University of Oxford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.ac.ox.it.ords.security.model;

/**
* Configuration and credentials for a database server
*/
public class DatabaseServer {

private String host;
private int port;
private String username;
private String password;

/**
* The database to connect to when no specific database is indicated; for on-premise this is typically "postgres"
* but for cloud database servers is either a random GUID or the username
*/
private String masterDatabaseName;

public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMasterDatabaseName() {
return masterDatabaseName;
}
public void setMasterDatabaseName(String masterDatabaseName) {
this.masterDatabaseName = masterDatabaseName;
}

public String getUrl(){
return "jdbc:postgresql://" + this.getHost() + ":" + this.getPort() + "/" + this.getMasterDatabaseName();
}

public String getUrl(String database){
return "jdbc:postgresql://" + this.getHost() + ":" + this.getPort() + "/" + database;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2015 University of Oxford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.ac.ox.it.ords.security.services;

import java.util.List;
import java.util.ServiceLoader;

import uk.ac.ox.it.ords.security.model.DatabaseServer;
import uk.ac.ox.it.ords.security.services.impl.ServerConfigurationServiceImpl;

/**
* Interface for obtaining credentials for database servers. The default implementation
* stores credentials in a configuration file on the server file system, but other
* implementations could use a database table, registry, or external API
*/
public interface ServerConfigurationService {

/**
* Gets the specified database server
* @return a DatabaseServer instance
* @throws Exception if the database configuration file is corrupt
*/
public DatabaseServer getDatabaseServer(String host) throws Exception;

/**
* Gets the preferred database server to use for user data
* @return a DatabaseServer instance
* @throws Exception if the database configuration file is corrupt
*/
public DatabaseServer getDatabaseServer() throws Exception;

/**
* Gets the preferred database server to use for internal metadata
* @return a DatabaseServer instance
* @throws Exception if the database configuration file is corrupt
*/
public DatabaseServer getOrdsDatabaseServer() throws Exception;

/**
* Gets all configured database servers
* @return a List of DatabaseServers
* @throws Exception if the database configuration file is corrupt
*/
public List<DatabaseServer> getAllDatabaseServers() throws Exception;

/**
* Factory for obtaining implementations
*/
public static class Factory {
private static ServerConfigurationService provider;
public static ServerConfigurationService getInstance() {
//
// Use the service loader to load an implementation if one is available
// Place a file called uk.ac.ox.oucs.ords.utilities.csv in src/main/resources/META-INF/services
// containing the classname to load as the CsvService implementation.
// By default we load the Hibernate implementation.
//
if (provider == null){
ServiceLoader<ServerConfigurationService> ldr = ServiceLoader.load(ServerConfigurationService.class);
for (ServerConfigurationService service : ldr) {
// We are only expecting one
provider = service;
}
}
//
// If no service provider is found, use the default
//
if (provider == null){
provider = ServerConfigurationServiceImpl.getInstance();
}

return provider;
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright 2015 University of Oxford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.ac.ox.it.ords.security.services.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.configuration.XMLConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import uk.ac.ox.it.ords.security.configuration.MetaConfiguration;
import uk.ac.ox.it.ords.security.model.DatabaseServer;
import uk.ac.ox.it.ords.security.services.ServerConfigurationService;

/**
* Default implementation of the database credentials interface that stores
* credentials in a file on the server.
*/
public class ServerConfigurationServiceImpl implements ServerConfigurationService {

public static Logger log = LoggerFactory.getLogger(ServerConfigurationServiceImpl.class);

/**
* The default configuration location; this can be overridden in config.xml to point
* to another file.
*/
public static final String DEFAULT_SERVER_CONFIG_LOCATION = "databaseservers.xml";

/**
* Singleton instance
*/
private static ServerConfigurationServiceImpl instance;

/**
* Private constructor for singleton
*/
private ServerConfigurationServiceImpl(){
try {
load();
} catch (Exception e) {
log.error("Couldn't load database server credentials");
}
}

/**
* Get the service instance
* @return the service instance
*/
public static ServerConfigurationServiceImpl getInstance(){
if (instance == null) instance = new ServerConfigurationServiceImpl();

return instance;
}

/**
* The servers defined in the configuration file
*/
private List<DatabaseServer> servers;

/**
* The server for the internal metadata
*/
private DatabaseServer metadataServer;

/**
* Loads the configuration file
* @return
* @throws Exception
*/
protected void load() throws Exception {

String serverConfigurationLocation = DEFAULT_SERVER_CONFIG_LOCATION;

//
// Check if there is a different load location from the default
//
try {
serverConfigurationLocation = MetaConfiguration.getConfiguration().getString("ords.server.configuration");
if (serverConfigurationLocation == null){
log.debug("No server configuration location set; using defaults");
serverConfigurationLocation = DEFAULT_SERVER_CONFIG_LOCATION;
}
} catch (Exception e) {
log.debug("No server configuration location set; using defaults");
serverConfigurationLocation = DEFAULT_SERVER_CONFIG_LOCATION;
}

//
// Load the Server Configuration file
//
XMLConfiguration xmlServerConfiguration = new XMLConfiguration();
try {
xmlServerConfiguration.setFileName(serverConfigurationLocation);
xmlServerConfiguration.load();
} catch (Exception e1) {
log.error("Cannot read server configuration at " + serverConfigurationLocation);
throw new Exception("Cannot read server configuration");
}

//
// Read the server list
//
int serverArray = xmlServerConfiguration.getStringArray("server[@host]").length;

servers = new ArrayList<DatabaseServer>();

for (int i = 0; i < serverArray; i++){
DatabaseServer databaseServer = new DatabaseServer();

databaseServer.setHost(xmlServerConfiguration.getString("server("+i+")[@host]"));
databaseServer.setPort(xmlServerConfiguration.getInt("server("+i+")[@port]"));
databaseServer.setUsername(xmlServerConfiguration.getString("server("+i+")[@username]"));
databaseServer.setPassword(xmlServerConfiguration.getString("server("+i+")[@password]"));
databaseServer.setMasterDatabaseName(xmlServerConfiguration.getString("server("+i+")[@database]"));

servers.add(databaseServer);
}

metadataServer = new DatabaseServer();
metadataServer.setHost(xmlServerConfiguration.getString("metadata(0)[@host]"));
metadataServer.setPort(xmlServerConfiguration.getInt("metadata(0)[@port]"));
metadataServer.setUsername(xmlServerConfiguration.getString("metadata(0)[@username]"));
metadataServer.setPassword(xmlServerConfiguration.getString("metadata(0)[@password]"));
metadataServer.setMasterDatabaseName(xmlServerConfiguration.getString("metadata(0)[@database]"));

}

@Override
public DatabaseServer getDatabaseServer() throws Exception {
return servers.get(0);
}

@Override
public List<DatabaseServer> getAllDatabaseServers() throws Exception {
return servers;
}

@Override
public DatabaseServer getDatabaseServer(String host) throws Exception {
for (DatabaseServer databaseServer : servers){
if (databaseServer.getHost().equalsIgnoreCase(host)){
return databaseServer;
}
}
return null;
}

@Override
public DatabaseServer getOrdsDatabaseServer() throws Exception {
return metadataServer;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@

import uk.ac.ox.it.ords.security.configuration.MetaConfiguration;
import uk.ac.ox.it.ords.security.model.Audit;
import uk.ac.ox.it.ords.security.model.DatabaseServer;
import uk.ac.ox.it.ords.security.model.Permission;
import uk.ac.ox.it.ords.security.model.UserRole;
import uk.ac.ox.it.ords.security.services.ServerConfigurationService;

public class HibernateUtils
{
Expand All @@ -54,7 +56,12 @@ protected static void init()
{
try
{
String hibernateConfigLocation = MetaConfiguration.getConfiguration().getString(HIBERNATE_CONFIGURATION_PROPERTY);
String hibernateConfigLocation;
try {
hibernateConfigLocation = MetaConfiguration.getConfiguration().getString(HIBERNATE_CONFIGURATION_PROPERTY);
} catch (Exception e) {
hibernateConfigLocation = null;
}
if (hibernateConfigLocation == null){
log.warn("No hibernate configuration found; using default hibernate.cfg.xml");
configuration = new Configuration().configure();
Expand All @@ -63,6 +70,14 @@ protected static void init()
configuration = new Configuration().configure(new File(hibernateConfigLocation));
}

//
// Add server connection details
//
DatabaseServer databaseServer = ServerConfigurationService.Factory.getInstance().getOrdsDatabaseServer();
configuration.setProperty("hibernate.connection.url", databaseServer.getUrl());
configuration.setProperty("hibernate.connection.username", databaseServer.getUsername());
configuration.setProperty("hibernate.connection.password", databaseServer.getPassword());

//
// Add class mappings. Note we do this programmatically as this is
// completely independent of the database configuration.
Expand All @@ -72,7 +87,7 @@ protected static void init()
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
catch (HibernateException he)
catch (Exception he)
{
throw new ExceptionInInitializerError(he);
}
Expand Down
Loading

0 comments on commit 623eb72

Please sign in to comment.