Skip to content

Commit

Permalink
#2270: wip - settings.yml not being read for some classes?
Browse files Browse the repository at this point in the history
  • Loading branch information
DarioGii committed Dec 20, 2024
1 parent 3380108 commit f072de8
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.provider.UnsupportedProviderException;

@Getter
@Slf4j
@Configuration
public class DatabaseConfig {

public static final String DOCKER_HOST = "://db:";
public static final String LOCALHOST = "://localhost:";
public static final String POSTGRES = "postgres";
public static final String DATASOURCE_PREFIX = "jdbc";
public static final String DATASOURCE_URL_TEMPLATE = "jdbc:%s://%s:%4d/%s";

private final ApplicationProperties applicationProperties;

Expand All @@ -31,12 +29,15 @@ public DatabaseConfig(@Autowired ApplicationProperties applicationProperties) {
}

/**
* Creates the <code>DataSource</code> for the connection to the DB. If the active profile is
* set to <em>'default'</em> it will use local configiration, namely using localhost as the host
* for the connection. If set to <em>'docker'</em> it will use the Dokcer server configuration.
* Creates the <code>DataSource</code> for the connection to the DB. If <code>useDefault</code>
* is set to <code>true</code>, it will use the default H2 DB. If it is set to <code>false
* </code>, it will use the user's custom configuration set in the settings.yml.
*
* @return a <code>DataSource</code> using the configuration settings in the settings.yml
* @throws UnsupportedProviderException if the type of database selected is not supported
*/
@Bean
public DataSource dataSource() {
public DataSource dataSource() throws UnsupportedProviderException {
ApplicationProperties.System system = applicationProperties.getSystem();
ApplicationProperties.Datasource datasource = system.getDatasource();
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
Expand All @@ -51,57 +52,72 @@ public DataSource dataSource() {
return dataSourceBuilder.build();
}

dataSourceBuilder.driverClassName(
getDriverClassName(
ApplicationProperties.Driver.valueOf(datasource.getType().toUpperCase())));
dataSourceBuilder.url(getDataSourceUrl(datasource));
dataSourceBuilder.driverClassName(getDriverClassName(datasource.getType()));
dataSourceBuilder.url(
getDataSourceUrl(
datasource.getType(),
datasource.getHostName(),
datasource.getPort(),
datasource.getName()));
dataSourceBuilder.username(datasource.getUsername());
dataSourceBuilder.password(datasource.getPassword());

return dataSourceBuilder.build();
}

private String getDataSourceUrl(ApplicationProperties.Datasource datasource) {
return DATASOURCE_PREFIX
+ ":"
+ datasource.getType()
+ "://"
+ datasource.getHostName()
+ ":"
+ datasource.getPort()
+ "/"
+ datasource.getName();
/**
* Generate the URL the <code>DataSource</code> will use to connect to the database
*
* @param dataSourceType the type of the database
* @param hostname the host name
* @param port the port number to use for the database
* @param dataSourceName the name the database to connect to
* @return the <code>DataSource</code> URL
*/
private String getDataSourceUrl(
String dataSourceType, String hostname, Integer port, String dataSourceName) {
return DATASOURCE_URL_TEMPLATE.formatted(dataSourceType, hostname, port, dataSourceName);
}

public Connection connection() throws SQLException {
/**
* @return a <code>Connection</code> using the configured <code>DataSource</code>
* @throws SQLException if a database access error occurs
* @throws UnsupportedProviderException when an unsupported database is selected
*/
public Connection connection() throws SQLException, UnsupportedProviderException {
return dataSource().getConnection();
}

/**
* Selects the DB driver based on the <code>stirling.software.SPDF.model.Driver</code> chosen.
* Selects the database driver based on the type of database chosen.
*
* @param driverName the type of the driver (e.g. 'h2', 'postgresql')
* @return the fully qualified driver for the database chosen
* @throws UnsupportedProviderException when an unsupported database is selected
*/
private String getDriverClassName(ApplicationProperties.Driver driverName) {
switch (driverName) {
case H2 -> {
log.debug("H2 driver selected");
return "org.h2.Driver";
}
case POSTGRESQL -> {
log.debug("Postgres driver selected");
return "org.postgresql.Driver";
}
case ORACLE -> {
log.debug("Oracle driver selected");
return "oracle.jdbc.OracleDriver";
}
case MY_SQL -> {
log.debug("MySQL driver selected");
return "com.mysql.cj.jdbc.Driver";
}
default -> {
log.debug("Defaulting to H2 driver");
return "org.h2.Driver";
private String getDriverClassName(String driverName) throws UnsupportedProviderException {
try {
ApplicationProperties.Driver driver =
ApplicationProperties.Driver.valueOf(driverName.toUpperCase());

switch (driver) {
case H2 -> {
log.debug("H2 driver selected");
return "org.h2.Driver";
}
case POSTGRESQL -> {
log.debug("Postgres driver selected");
return "org.postgresql.Driver";
}
default -> {
log.warn("{} driver selected", driverName);
throw new UnsupportedProviderException(
driverName + " is not currently supported");
}
}
} catch (IllegalArgumentException e) {
log.warn("Unknown driver: {}", driverName);
throw new UnsupportedProviderException(driverName + " is not currently supported");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
import stirling.software.SPDF.utils.FileInfo;

@Slf4j
Expand Down Expand Up @@ -124,7 +125,7 @@ public void exportDatabase() {
conn, new EncodedResource(new PathResource(insertOutputFilePath)));

log.info("Database export completed: {}", insertOutputFilePath);
} catch (SQLException e) {
} catch (SQLException | UnsupportedProviderException e) {
log.error("Error during database export: {}", e.getMessage(), e);
} catch (ScriptException e) {
log.error("Error during database export: File {} not found", insertOutputFilePath);
Expand Down Expand Up @@ -156,7 +157,7 @@ public String getH2Version() {
log.info("H2 Database Version: {}", version);
}
}
} catch (SQLException e) {
} catch (SQLException | UnsupportedProviderException e) {
log.error("Error retrieving H2 version: {}", e.getMessage(), e);
}
return version;
Expand Down Expand Up @@ -192,7 +193,7 @@ private void executeDatabaseScript(Path scriptPath) {
ScriptUtils.executeSqlScript(conn, new EncodedResource(new PathResource(scriptPath)));

log.info("Database import completed: {}", scriptPath);
} catch (SQLException e) {
} catch (SQLException | UnsupportedProviderException e) {
log.error("Error during database import: {}", e.getMessage(), e);
} catch (ScriptException e) {
log.error("Error: File {} not found", scriptPath.toString(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.Driver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -240,7 +239,6 @@ public Provider get(String registrationId) throws UnsupportedProviderException {

@Data
public static class System {
private Boolean localEnv;
private String defaultLocale;
private Boolean googlevisibility;
private boolean showUpdate;
Expand All @@ -249,33 +247,42 @@ public static class System {
private String tessdataDir;
private Boolean enableAlphaFunctionality;
private String enableAnalytics;
private String environmentName;
private Datasource datasource;
}

@Data
public static class Datasource {
private boolean useDefault;
private String name;
private String type;
private String hostName;
private String port;
private String defaultUrl;
private Integer port;
private String name;
private String username;
@ToString.Exclude private String password;
private boolean useDefault;
private final String defaultUrl;
}

public enum Driver {
H2("h2"),
POSTGRESQL("postgresql"),
ORACLE("oracle"),
MY_SQL("mysql");
MYSQL("mysql");

private final String driverName;

Driver(String driverName) {
this.driverName = driverName;
}

@Override
public String toString() {
return """
Driver {
driverName='%s'
}
"""
.formatted(driverName);
}
}

@Data
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=false
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
#spring.jpa.database-platform=org.hibernate.dialect.H2Dialect todo: check if needed
server.servlet.session.timeout=30m
# Change the default URL path for OpenAPI JSON
springdoc.api-docs.path=/v1/api-docs
Expand Down
14 changes: 7 additions & 7 deletions src/main/resources/settings.yml.template
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ system:
tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored.
enableAnalytics: undefined # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true
datasource:
type: postgresql
hostName: localhost
port: 5432
name: postgres
useDefault: false
type: 'postgresql' # the type of the database to set (e.g. 'h2', 'postgresql')
hostName: 'localhost' # the host name to use for the database url. Set to 'localhost' when running the app locally. Set to match the name of the container name of your database container when running the app on a server (Docker configuration)
port: 5432 # set the port number of the database. Ensure this matches the port the database is listening to
name: 'postgres' # set the name of your database. Should match the name of the database you create
username: 'postgres' # set the database username
password: 'postgres' # set the database password
useDefault: 'false' # set this property to 'true' if you would like to use the default database configuration
defaultUrl: jdbc:h2:file:./configs/stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: postgres
password: postgres

ui:
appName: '' # application's visible name
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package stirling.software.SPDF.config.security.database;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.provider.UnsupportedProviderException;

import javax.sql.DataSource;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class DatabaseConfigTest {

@Mock
private ApplicationProperties applicationProperties;

@InjectMocks
private DatabaseConfig databaseConfig;

@Test
void testDefaultConfigurationForDataSource() throws UnsupportedProviderException {
var system = mock(ApplicationProperties.System.class);
var datasource = mock(ApplicationProperties.Datasource.class);
var testUrl = "jdbc:h2:mem:test";

when(applicationProperties.getSystem()).thenReturn(system);
when(system.getDatasource()).thenReturn(datasource);
when(datasource.isUseDefault()).thenReturn(true);
when(datasource.getDefaultUrl()).thenReturn(testUrl);

var result = databaseConfig.dataSource();

assertInstanceOf(DataSource.class, result);
}

@Test
void testCustomConfigurationForDataSource() throws UnsupportedProviderException {
var system = mock(ApplicationProperties.System.class);
var datasource = mock(ApplicationProperties.Datasource.class);

when(applicationProperties.getSystem()).thenReturn(system);
when(system.getDatasource()).thenReturn(datasource);
when(datasource.isUseDefault()).thenReturn(false);
when(datasource.getType()).thenReturn("postgresql");
when(datasource.getHostName()).thenReturn("localhost");
when(datasource.getPort()).thenReturn(5432);
when(datasource.getName()).thenReturn("postgres");
when(datasource.getUsername()).thenReturn("postgres");
when(datasource.getPassword()).thenReturn("postgres");

var result = databaseConfig.dataSource();

assertInstanceOf(DataSource.class, result);
}

@ParameterizedTest(name = "Exception thrown when the DB type [{arguments}] is not supported")
@ValueSource(strings = {"oracle", "mysql", "mongoDb"})
void exceptionThrownWhenDBTypeIsUnsupported(String datasourceType) {
var system = mock(ApplicationProperties.System.class);
var datasource = mock(ApplicationProperties.Datasource.class);

when(applicationProperties.getSystem()).thenReturn(system);
when(system.getDatasource()).thenReturn(datasource);
when(datasource.isUseDefault()).thenReturn(false);
when(datasource.getType()).thenReturn(datasourceType);

assertThrows(UnsupportedProviderException.class, () -> databaseConfig.dataSource());
}
}

0 comments on commit f072de8

Please sign in to comment.