diff --git a/src/main/java/org/utplsql/cli/ConnectionConfig.java b/src/main/java/org/utplsql/cli/ConnectionConfig.java new file mode 100644 index 0000000..b98c6a5 --- /dev/null +++ b/src/main/java/org/utplsql/cli/ConnectionConfig.java @@ -0,0 +1,38 @@ +package org.utplsql.cli; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ConnectionConfig { + + private final String user; + private final String password; + private final String connect; + + public ConnectionConfig( String connectString ) { + Matcher m = Pattern.compile("^([^/]+)/([^@]+)@(.*)$").matcher(connectString); + if ( m.find() ) { + user = m.group(1); + password = m.group(2); + connect = m.group(3); + } + else + throw new IllegalArgumentException("Not a valid connectString: '" + connectString + "'"); + } + + public String getConnect() { + return connect; + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + + public String getConnectString() { + return user + "/" + password + "@" + connect; + } +} diff --git a/src/main/java/org/utplsql/cli/ConnectionInfoBuilder.java b/src/main/java/org/utplsql/cli/ConnectionInfoBuilder.java new file mode 100644 index 0000000..b573927 --- /dev/null +++ b/src/main/java/org/utplsql/cli/ConnectionInfoBuilder.java @@ -0,0 +1,5 @@ +package org.utplsql.cli; + +public class ConnectionInfoBuilder { + +} diff --git a/src/main/java/org/utplsql/cli/DataSourceProvider.java b/src/main/java/org/utplsql/cli/DataSourceProvider.java index ac790f4..394b432 100644 --- a/src/main/java/org/utplsql/cli/DataSourceProvider.java +++ b/src/main/java/org/utplsql/cli/DataSourceProvider.java @@ -2,9 +2,11 @@ import com.zaxxer.hikari.HikariDataSource; import org.utplsql.api.EnvironmentVariableUtil; +import org.utplsql.cli.datasource.TestedDataSourceProvider; import javax.sql.DataSource; import java.io.File; +import java.sql.SQLException; /** Helper class to give you a ready-to-use datasource * @@ -13,19 +15,20 @@ public class DataSourceProvider { static { - String oracleHome = EnvironmentVariableUtil.getEnvValue("ORACLE_HOME"); - if (oracleHome != null) { + String oracleHome = System.getenv("ORACLE_HOME"); + if (oracleHome != null && System.getProperty("oracle.net.tns_admin") == null) { System.setProperty("oracle.net.tns_admin", String.join(File.separator, oracleHome, "NETWORK", "ADMIN")); } } - public static DataSource getDataSource(ConnectionInfo info, int maxConnections ) { + public static DataSource getDataSource(ConnectionInfo info, int maxConnections ) throws SQLException { requireOjdbc(); - HikariDataSource pds = new HikariDataSource(); - pds.setJdbcUrl("jdbc:oracle:thin:" + info.getConnectionString()); + ConnectionConfig config = new ConnectionConfig(info.getConnectionString()); + + HikariDataSource pds = new TestedDataSourceProvider(config).getDataSource(); pds.setAutoCommit(false); pds.setMaximumPoolSize(maxConnections); return pds; diff --git a/src/main/java/org/utplsql/cli/ReportersCommand.java b/src/main/java/org/utplsql/cli/ReportersCommand.java index 80f01ff..32624eb 100644 --- a/src/main/java/org/utplsql/cli/ReportersCommand.java +++ b/src/main/java/org/utplsql/cli/ReportersCommand.java @@ -31,14 +31,15 @@ private ConnectionInfo getConnectionInfo() { @Override public int run() { - DataSource ds = DataSourceProvider.getDataSource(getConnectionInfo(), 1); - try (Connection con = ds.getConnection() ) { + try { + DataSource ds = DataSourceProvider.getDataSource(getConnectionInfo(), 1); + try (Connection con = ds.getConnection()) { - ReporterFactory reporterFactory = ReporterFactoryProvider.createReporterFactory(con); + ReporterFactory reporterFactory = ReporterFactoryProvider.createReporterFactory(con); - writeReporters(ReporterInspector.create(reporterFactory, con).getReporterInfos(), System.out); - } - catch ( Exception e ) { + writeReporters(ReporterInspector.create(reporterFactory, con).getReporterInfos(), System.out); + } + } catch (Exception e) { e.printStackTrace(); return 1; } diff --git a/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java b/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java new file mode 100644 index 0000000..4ad5d62 --- /dev/null +++ b/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java @@ -0,0 +1,81 @@ +package org.utplsql.cli.datasource; + +import com.zaxxer.hikari.HikariDataSource; +import org.utplsql.cli.ConnectionConfig; +import org.utplsql.cli.exception.DatabaseConnectionFailed; + +import java.io.File; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class TestedDataSourceProvider { + + interface ConnectStringPossibility { + String getConnectString(ConnectionConfig config); + String getMaskedConnectString(ConnectionConfig config); + } + + + private final ConnectionConfig config; + private List possibilities = new ArrayList<>(); + + public TestedDataSourceProvider(ConnectionConfig config) { + this.config = config; + + possibilities.add(new ThickConnectStringPossibility()); + possibilities.add(new ThinConnectStringPossibility()); + } + + public HikariDataSource getDataSource() throws SQLException { + + HikariDataSource ds = new HikariDataSource(); + + testAndSetJdbcUrl(ds); + + return ds; + } + + public void testAndSetJdbcUrl( HikariDataSource ds ) throws SQLException + { + List errors = new ArrayList<>(); + Throwable lastException = null; + for (ConnectStringPossibility possibility : possibilities) { + ds.setJdbcUrl(possibility.getConnectString(config)); + try (Connection con = ds.getConnection()) { + return; + } catch (UnsatisfiedLinkError | Exception e) { + errors.add(possibility.getMaskedConnectString(config) + ": " + e.getMessage()); + lastException = e; + } + } + + errors.forEach(System.out::println); + throw new DatabaseConnectionFailed(lastException); + } + + private static class ThickConnectStringPossibility implements ConnectStringPossibility { + @Override + public String getConnectString(ConnectionConfig config) { + return "jdbc:oracle:oci8:" + config.getConnectString(); + } + + @Override + public String getMaskedConnectString(ConnectionConfig config) { + return "jdbc:oracle:oci8:****/****@" + config.getConnect(); + } + } + + private static class ThinConnectStringPossibility implements ConnectStringPossibility { + @Override + public String getConnectString(ConnectionConfig config) { + return "jdbc:oracle:thin:" + config.getConnectString(); + } + + @Override + public String getMaskedConnectString(ConnectionConfig config) { + return "jdbc:oracle:thin:****/****@" + config.getConnect(); + } + } +} diff --git a/src/main/java/org/utplsql/cli/exception/DatabaseConnectionFailed.java b/src/main/java/org/utplsql/cli/exception/DatabaseConnectionFailed.java index 01b03db..2a521cd 100644 --- a/src/main/java/org/utplsql/cli/exception/DatabaseConnectionFailed.java +++ b/src/main/java/org/utplsql/cli/exception/DatabaseConnectionFailed.java @@ -4,7 +4,7 @@ public class DatabaseConnectionFailed extends SQLException { - public DatabaseConnectionFailed(SQLException cause ) { + public DatabaseConnectionFailed(Throwable cause ) { super( "Could not establish connection to database. Reason: " + cause.getMessage(), cause); } } diff --git a/src/test/java/org/utplsql/cli/DataSourceProviderIT.java b/src/test/java/org/utplsql/cli/DataSourceProviderIT.java new file mode 100644 index 0000000..56a254c --- /dev/null +++ b/src/test/java/org/utplsql/cli/DataSourceProviderIT.java @@ -0,0 +1,23 @@ +package org.utplsql.cli; + +import org.junit.jupiter.api.Test; +import org.utplsql.cli.datasource.TestedDataSourceProvider; + +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.SQLException; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class DataSourceProviderIT { + + @Test + public void connectToDatabase() throws IOException, SQLException { + + ConnectionConfig config = new ConnectionConfig(TestHelper.getConnectionString()); + + DataSource dataSource = new TestedDataSourceProvider(config).getDataSource(); + + assertNotNull(dataSource); + } +} diff --git a/src/test/java/org/utplsql/cli/RunCommandCoverageReporterIT.java b/src/test/java/org/utplsql/cli/RunCommandCoverageReporterIT.java index 4a1c6af..1b0fa36 100644 --- a/src/test/java/org/utplsql/cli/RunCommandCoverageReporterIT.java +++ b/src/test/java/org/utplsql/cli/RunCommandCoverageReporterIT.java @@ -103,7 +103,7 @@ public void coverageReporterWriteAssetsToOutput() throws Exception { // Check correct script-part in HTML source exists String content = new String(Files.readAllBytes(coveragePath)); - assertTrue(content.contains("