diff --git a/README.md b/README.md index b5525cd..fdb7750 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,14 @@ You can download development versions on [Bintray](https://bintray.com/viniciusa * ~~When using reporters for Sonar or Coveralls client needs to be invoked from project's root directory.~~ ## Usage -utplsql run user/password@database [-p=(ut_path|ut_paths)] [-f=format [-o=output_file] [-s] ...] +utplsql run user/pass@[[host][:port]/]db [-p=(ut_path|ut_paths)] [-f=format [-o=output_file] [-s] ...] ``` -user - username to connect as. -password - password of the user. -database - database to connect to. +user - Username to connect as. +password - Password of the user. +host - Server address, defaults to 127.0.0.1. +port - Server port, defaults to 1521. +db - Database to connect to. -p=suite_path(s) - A suite path or a comma separated list of suite paths for unit test to be executed. The path(s) can be in one of the following formats: schema[.package[.procedure]] diff --git a/src/main/java/io/github/utplsql/cli/ConnectionInfo.java b/src/main/java/io/github/utplsql/cli/ConnectionInfo.java index 4523537..5f8deac 100644 --- a/src/main/java/io/github/utplsql/cli/ConnectionInfo.java +++ b/src/main/java/io/github/utplsql/cli/ConnectionInfo.java @@ -5,24 +5,12 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Created by Vinicius on 21/04/2017. */ public class ConnectionInfo { - /** - * Regex pattern to match following connection strings: - * user/pass@127.0.0.1:1521/db - * user/pass@127.0.0.1/db - * user/pass@db - */ - private static final String CONNSTR_PATTERN = - "^(?[0-9a-z]+)/(?[0-9a-z]+)" + - "(?:(?:@(?[^:/]+)?(?::(?[0-9]+))?(?:/(?[0-9a-z]+))$)|(?:@(?[0-9a-z]+)$))"; - private static final String DEFAULT_HOST = "127.0.0.1"; private static final int DEFAULT_PORT = 1521; @@ -30,36 +18,79 @@ public class ConnectionInfo { private String password; private String host; private int port; - private String db; + private String database; - public ConnectionInfo() { - } + public ConnectionInfo() {} public Connection getConnection() throws SQLException { return DriverManager.getConnection(getConnectionUrl(), getUser(), getPassword()); } - public ConnectionInfo parseConnectionString(String connectionString) throws ParameterException { - Pattern p = Pattern.compile(CONNSTR_PATTERN); - Matcher m = p.matcher(connectionString); + public ConnectionInfo parseConnectionString(String connectionString) + throws ParameterException, IllegalArgumentException { + + if (connectionString == null || connectionString.isEmpty()) + throw invalidConnectionString(); - if (!m.matches()) - throw new ParameterException("Invalid connection string!"); + int i = connectionString.lastIndexOf("@"); + if (i == -1) + throw invalidConnectionString(); - this.setUser(m.group("user")); - this.setPassword(m.group("pass")); - this.setHost(m.group("host") != null ? m.group("host") : DEFAULT_HOST); - this.setPort(m.group("port") != null ? Integer.parseInt(m.group("port")) : DEFAULT_PORT); - this.setDb(m.group("db1") != null ? m.group("db1") : m.group("db2")); + String credentials = connectionString.substring(0, i); + String host = connectionString.substring(i+1); + parseCredentials(credentials); + parseHost(host); return this; } + private void parseCredentials(String str) throws ParameterException, IllegalArgumentException { + int barIdx = str.indexOf("/"); + + if (barIdx == -1 || barIdx == 0 || barIdx == str.length() - 1) + throw invalidConnectionString(); + + this.setUser(str.substring(0, barIdx)); + this.setPassword(str.substring(barIdx+1)); + } + + private void parseHost(String str) throws ParameterException, IllegalArgumentException { + if (str == null || str.isEmpty()) + throw invalidConnectionString(); + + int colonIdx = str.indexOf(":"); + int barIdx = str.indexOf("/"); + + if ((colonIdx != -1 && barIdx == -1) || barIdx == 0) // @host:port or // @/db + throw invalidConnectionString(); + + if (colonIdx != -1) { // @host:port/db + setHost(str.substring(0, colonIdx)); + setPort(Integer.parseInt(str.substring(colonIdx + 1, barIdx))); + setDatabase(str.substring(barIdx + 1)); + } + else + if (barIdx != -1) { // @host/db + setHost(str.substring(0, barIdx)); + setPort(DEFAULT_PORT); + setDatabase(str.substring(barIdx + 1)); + } + else { // @db + setHost(DEFAULT_HOST); + setPort(DEFAULT_PORT); + setDatabase(str); + } + } + + private ParameterException invalidConnectionString() { + return new ParameterException("Invalid connection string."); + } + public String getUser() { return user; } - public void setUser(String user) { + private void setUser(String user) { this.user = user; } @@ -67,7 +98,7 @@ public String getPassword() { return password; } - public void setPassword(String password) { + private void setPassword(String password) { this.password = password; } @@ -75,7 +106,7 @@ public String getHost() { return host; } - public void setHost(String host) { + private void setHost(String host) { this.host = host; } @@ -83,25 +114,25 @@ public int getPort() { return port; } - public void setPort(int port) { + private void setPort(int port) { this.port = port; } - public String getDb() { - return db; + public String getDatabase() { + return database; } - public void setDb(String db) { - this.db = db; + private void setDatabase(String database) { + this.database = database; } public String getConnectionUrl() { - return String.format("jdbc:oracle:thin:@//%s:%d/%s", getHost(), getPort(), getDb()); + return String.format("jdbc:oracle:thin:@//%s:%d/%s", getHost(), getPort(), getDatabase()); } @Override public String toString() { - return String.format("%s@%s:%d/%s", getUser(), getHost(), getPort(), getDb()); + return String.format("%s@%s:%d/%s", getUser(), getHost(), getPort(), getDatabase()); } } diff --git a/src/test/java/io/github/utplsql/cli/ConnectionInfoTest.java b/src/test/java/io/github/utplsql/cli/ConnectionInfoTest.java index e2981cf..a48ef77 100644 --- a/src/test/java/io/github/utplsql/cli/ConnectionInfoTest.java +++ b/src/test/java/io/github/utplsql/cli/ConnectionInfoTest.java @@ -11,66 +11,124 @@ public class ConnectionInfoTest { /** * Regex pattern to match following connection strings: - * user/pass@127.0.0.1:1521/db - * user/pass@127.0.0.1/db + * user/pass@host:port/db + * user/pass@host/db * user/pass@db - * user/pass */ @Test - public void connectionStr_Full() { + public void valid_Full() { try { - ConnectionInfo ci = new ConnectionInfo().parseConnectionString("user/pass@localhost:3000/db"); - Assert.assertEquals("user", ci.getUser()); - Assert.assertEquals("pass", ci.getPassword()); - Assert.assertEquals("localhost", ci.getHost()); + ConnectionInfo ci = new ConnectionInfo() + .parseConnectionString("my_user/p@ss!@some.server.123-abc.com:3000/db_1.acme.com"); + Assert.assertEquals("my_user", ci.getUser()); + Assert.assertEquals("p@ss!", ci.getPassword()); + Assert.assertEquals("some.server.123-abc.com", ci.getHost()); Assert.assertEquals(3000, ci.getPort()); - Assert.assertEquals("db", ci.getDb()); - Assert.assertEquals("user@localhost:3000/db", ci.toString()); - Assert.assertEquals("jdbc:oracle:thin:@//localhost:3000/db", ci.getConnectionUrl()); + Assert.assertEquals("db_1.acme.com", ci.getDatabase()); + Assert.assertEquals("my_user@some.server.123-abc.com:3000/db_1.acme.com", ci.toString()); + Assert.assertEquals("jdbc:oracle:thin:@//some.server.123-abc.com:3000/db_1.acme.com", ci.getConnectionUrl()); } catch (Exception e) { Assert.fail(e.getMessage()); } } @Test - public void connectionStr_WithoutPort() { + public void valid_WithoutPort() { try { - ConnectionInfo ci = new ConnectionInfo().parseConnectionString("user/pass@localhost/db"); - Assert.assertEquals("user", ci.getUser()); - Assert.assertEquals("pass", ci.getPassword()); - Assert.assertEquals("localhost", ci.getHost()); + ConnectionInfo ci = new ConnectionInfo() + .parseConnectionString("my_user/p@ss!@some.server.123-abc.com/db_1.acme.com"); + Assert.assertEquals("my_user", ci.getUser()); + Assert.assertEquals("p@ss!", ci.getPassword()); + Assert.assertEquals("some.server.123-abc.com", ci.getHost()); Assert.assertEquals(1521, ci.getPort()); - Assert.assertEquals("db", ci.getDb()); - Assert.assertEquals("user@localhost:1521/db", ci.toString()); - Assert.assertEquals("jdbc:oracle:thin:@//localhost:1521/db", ci.getConnectionUrl()); + Assert.assertEquals("db_1.acme.com", ci.getDatabase()); + Assert.assertEquals("my_user@some.server.123-abc.com:1521/db_1.acme.com", ci.toString()); + Assert.assertEquals("jdbc:oracle:thin:@//some.server.123-abc.com:1521/db_1.acme.com", ci.getConnectionUrl()); } catch (Exception e) { Assert.fail(e.getMessage()); } } @Test - public void connectionStr_WithoutHostAndPort() { + public void valid_WithoutHostAndPort() { try { - ConnectionInfo ci = new ConnectionInfo().parseConnectionString("user/pass@db"); - Assert.assertEquals("user", ci.getUser()); - Assert.assertEquals("pass", ci.getPassword()); + ConnectionInfo ci = new ConnectionInfo() + .parseConnectionString("my_user/p@ss!@127.0.0.1/db_1.acme.com"); + Assert.assertEquals("my_user", ci.getUser()); + Assert.assertEquals("p@ss!", ci.getPassword()); Assert.assertEquals("127.0.0.1", ci.getHost()); Assert.assertEquals(1521, ci.getPort()); - Assert.assertEquals("db", ci.getDb()); - Assert.assertEquals("user@127.0.0.1:1521/db", ci.toString()); - Assert.assertEquals("jdbc:oracle:thin:@//127.0.0.1:1521/db", ci.getConnectionUrl()); + Assert.assertEquals("db_1.acme.com", ci.getDatabase()); + Assert.assertEquals("my_user@127.0.0.1:1521/db_1.acme.com", ci.toString()); + Assert.assertEquals("jdbc:oracle:thin:@//127.0.0.1:1521/db_1.acme.com", ci.getConnectionUrl()); } catch (Exception e) { Assert.fail(e.getMessage()); } } @Test - public void connectionStr_Invalid() { + public void invalid_WithoutDatabase_1() { + try { + new ConnectionInfo().parseConnectionString("user/pass@"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + + @Test + public void invalid_WithoutDatabase_2() { try { new ConnectionInfo().parseConnectionString("user/pass"); Assert.fail(); } catch (ParameterException ignored) {} } + @Test + public void invalid_WithoutDatabase_3() { + try { + new ConnectionInfo().parseConnectionString("user/pass@localhost:1521"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + + @Test + public void invalid_WithoutHost() { + try { + new ConnectionInfo().parseConnectionString("user/pass@/db"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + + @Test + public void invalid_WithoutPassword() { + try { + new ConnectionInfo().parseConnectionString("user/@db"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + + @Test + public void invalid_WithoutUsername() { + try { + new ConnectionInfo().parseConnectionString("/pass@db"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + + @Test + public void invalid_WithoutUserPassDb_1() { + try { + new ConnectionInfo().parseConnectionString("/@db"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + + @Test + public void invalid_WithoutUserPass() { + try { + new ConnectionInfo().parseConnectionString("@db"); + Assert.fail(); + } catch (ParameterException ignored) {} + } + }