diff --git a/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java b/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java index eb2f7d2..0d37d66 100644 --- a/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java +++ b/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java @@ -17,10 +17,11 @@ package com.jd.jdbc.vitess; import com.jd.jdbc.common.Constant; -import com.jd.jdbc.vitess.mysql.VitessPropertyKey; import com.jd.jdbc.sqlparser.utils.StringUtils; +import com.jd.jdbc.vitess.mysql.VitessPropertyKey; import io.vitess.proto.Topodata; import java.nio.charset.Charset; +import java.sql.SQLException; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -57,42 +58,45 @@ public static void addDefaultProperties(Properties info) { } } - public static void checkCredentials(String path, Properties info) { + public static void checkCredentials(String path, Properties info) throws SQLException { if (!info.containsKey(VitessPropertyKey.USER.getKeyName()) || !info.containsKey(VitessPropertyKey.PASSWORD.getKeyName())) { - throw new IllegalArgumentException("no user or password: '" + path + "'"); + throw new SQLException("no user or password: '" + path + "'"); } } - public static void checkCell(Properties info) throws IllegalArgumentException { + public static void checkCell(Properties info) throws SQLException { if (info.getProperty("cell") == null) { - throw new IllegalArgumentException("no cell found in jdbc url"); + throw new SQLException("no cell found in jdbc url"); } String[] cells = info.getProperty("cell").split(","); if (cells.length < 1) { - throw new IllegalArgumentException("no cell found in jdbc url"); + throw new SQLException("no cell found in jdbc url"); } } - public static void checkSchema(String path) { + public static void checkSchema(String path) throws SQLException { if (path == null || !path.startsWith("/")) { - throw new IllegalArgumentException("wrong database name path: '" + path + "'"); + throw new SQLException("wrong database name path: '" + path + "'"); + } + if (path.equals("/")) { + throw new SQLException(" database name can not null"); } } - public static void checkServerTimezone(Properties info) { + public static void checkServerTimezone(Properties info) throws SQLException { String canonicalTimezone = info.getProperty(VitessPropertyKey.SERVER_TIMEZONE.getKeyName()); if (canonicalTimezone == null) { - throw new IllegalArgumentException("serverTimezone is not found in jdbc url"); + throw new SQLException("serverTimezone is not found in jdbc url"); } if (!"GMT".equalsIgnoreCase(canonicalTimezone) && "GMT".equals(TimeZone.getTimeZone(canonicalTimezone).getID())) { - throw new IllegalArgumentException("invalid serverTimezone in jdbc url"); + throw new SQLException("invalid serverTimezone in jdbc url"); } } - public static void checkCharacterEncoding(Properties properties) { + public static void checkCharacterEncoding(Properties properties) throws SQLException { String characterEncoding = properties.getProperty(VitessPropertyKey.characterEncoding.getKeyName()); if (StringUtils.isEmpty(characterEncoding)) { - throw new IllegalArgumentException("characterEncoding is not found in jdbc url"); + throw new SQLException("characterEncoding is not found in jdbc url"); } String csn = Charset.defaultCharset().name(); boolean characterEncodingFlag = "UTF-8".equalsIgnoreCase(characterEncoding) || "UTF8".equalsIgnoreCase(characterEncoding); @@ -100,7 +104,7 @@ public static void checkCharacterEncoding(Properties properties) { if (characterEncodingFlag && csnFlag) { return; } - throw new IllegalArgumentException("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = " + characterEncoding + ", file.encoding=" + csn); + throw new SQLException("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = " + characterEncoding + ", file.encoding=" + csn); } public static String getDefaultKeyspace(Properties props) { @@ -108,8 +112,8 @@ public static String getDefaultKeyspace(Properties props) { return keySpaces.get(0); } - public static Topodata.TabletType getTabletType(Properties props) { - String role = getRole(props); + public static Topodata.TabletType getTabletType(Properties props) throws SQLException { + String role = props.getProperty(Constant.DRIVER_PROPERTY_ROLE_KEY, Constant.DRIVER_PROPERTY_ROLE_RW); switch (role.toLowerCase()) { case Constant.DRIVER_PROPERTY_ROLE_RW: return Topodata.TabletType.MASTER; @@ -118,7 +122,7 @@ public static Topodata.TabletType getTabletType(Properties props) { case Constant.DRIVER_PROPERTY_ROLE_RO: return Topodata.TabletType.RDONLY; default: - throw new IllegalArgumentException("'role=" + role + "' " + "error in jdbc url"); + throw new SQLException("'role=" + role + "' " + "error in jdbc url"); } } diff --git a/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java b/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java index 549b9c8..f8eae1e 100755 --- a/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java +++ b/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java @@ -19,10 +19,10 @@ import com.jd.jdbc.common.Constant; import com.jd.jdbc.sqlparser.utils.StringUtils; import com.jd.jdbc.sqlparser.utils.Utils; -import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.checkSchema; import com.jd.jdbc.vitess.mysql.VitessPropertyKey; import java.net.URI; import java.net.URISyntaxException; +import java.sql.SQLException; import java.util.Properties; public class VitessJdbcUrlParser { @@ -31,8 +31,8 @@ public class VitessJdbcUrlParser { public static final String JDBC_VITESS_PREFIX = JDBC_PREFIX + "vitess:"; - public static Properties parse(String url, Properties info) { - if (!url.startsWith(JDBC_VITESS_PREFIX)) { + public static Properties parse(String url, Properties info) throws SQLException { + if (!acceptsUrl(url)) { throw new IllegalArgumentException("'" + JDBC_VITESS_PREFIX + "' prefix is mandatory"); } @@ -54,7 +54,7 @@ public static Properties parse(String url, Properties info) { parsedProperties.setProperty("port", String.valueOf(uri.getPort())); String path = uri.getPath(); - checkSchema(path); + VitessJdbcProperyUtil.checkSchema(path); parsedProperties.setProperty(Constant.DRIVER_PROPERTY_SCHEMA, path.substring(1)); diff --git a/src/test/java/com/jd/jdbc/discovery/EtcdTopoServerTest.java b/src/test/java/com/jd/jdbc/discovery/EtcdTopoServerTest.java index 5a7db0b..c96e314 100644 --- a/src/test/java/com/jd/jdbc/discovery/EtcdTopoServerTest.java +++ b/src/test/java/com/jd/jdbc/discovery/EtcdTopoServerTest.java @@ -36,6 +36,7 @@ import io.vitess.proto.Topodata; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; +import java.sql.SQLException; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -85,7 +86,7 @@ public static void afterClass() { } @Before - public void init() throws TopoException { + public void init() throws TopoException, SQLException { String connectionUrl = getConnectionUrl(Driver.of(TestSuiteShardSpec.TWO_SHARDS)); Properties prop = VitessJdbcUrlParser.parse(connectionUrl, null); keyspace = prop.getProperty(Constant.DRIVER_PROPERTY_SCHEMA); diff --git a/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java b/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java index 6d5d7b3..dcd1d59 100644 --- a/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java +++ b/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java @@ -107,7 +107,7 @@ public void testDual() throws SQLException { @Test public void testGBK2() throws SQLException { - thrown.expect(IllegalArgumentException.class); + thrown.expect(SQLException.class); thrown.expectMessage("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = GBK, file.encoding=UTF-8"); init("GBK"); } diff --git a/src/test/java/com/jd/jdbc/vitess/TimezoneConfigureTest.java b/src/test/java/com/jd/jdbc/vitess/TimezoneConfigureTest.java index 0176ca4..8ae817e 100644 --- a/src/test/java/com/jd/jdbc/vitess/TimezoneConfigureTest.java +++ b/src/test/java/com/jd/jdbc/vitess/TimezoneConfigureTest.java @@ -39,7 +39,7 @@ public void testServerTimezone() throws SQLException { @Test public void testNoServerTimezone() throws SQLException { - thrown.expect(IllegalArgumentException.class); + thrown.expect(SQLException.class); thrown.expectMessage("serverTimezone is not found in jdbc url"); String url = getConnectionUrl(Driver.of(TestSuiteShardSpec.TWO_SHARDS)); url = url.replaceAll("&serverTimezone=[^&]*", ""); @@ -49,7 +49,7 @@ public void testNoServerTimezone() throws SQLException { @Test public void testParameterNoValue() throws SQLException { - thrown.expect(IllegalArgumentException.class); + thrown.expect(SQLException.class); thrown.expectMessage("serverTimezone is not found in jdbc url"); String url = getConnectionUrl(Driver.of(TestSuiteShardSpec.TWO_SHARDS)); url = url.replaceAll("&serverTimezone=[^&]*", "&serverTimezone="); @@ -59,7 +59,7 @@ public void testParameterNoValue() throws SQLException { @Test public void testInvalidServerTimezone() throws SQLException { - thrown.expect(IllegalArgumentException.class); + thrown.expect(SQLException.class); thrown.expectMessage("invalid serverTimezone in jdbc url"); String url = getConnectionUrl(Driver.of(TestSuiteShardSpec.TWO_SHARDS)); url = url.replaceAll("&serverTimezone=[^&]*", "&serverTimezone=ST"); diff --git a/src/test/java/com/jd/jdbc/vitess/VitessDriverConnectionPoolTest.java b/src/test/java/com/jd/jdbc/vitess/VitessDriverConnectionPoolTest.java index 099c503..20a7d50 100644 --- a/src/test/java/com/jd/jdbc/vitess/VitessDriverConnectionPoolTest.java +++ b/src/test/java/com/jd/jdbc/vitess/VitessDriverConnectionPoolTest.java @@ -24,6 +24,7 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import io.vitess.proto.Topodata; + import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.sql.Connection; @@ -34,6 +35,7 @@ import java.util.Objects; import java.util.Properties; import java.util.Random; + import org.apache.commons.dbcp2.BasicDataSource; import org.apache.tomcat.jdbc.pool.DataSource; import org.junit.Assert; diff --git a/src/test/java/com/jd/jdbc/vitess/VitessJdbcUrlParserTest.java b/src/test/java/com/jd/jdbc/vitess/VitessJdbcUrlParserTest.java new file mode 100644 index 0000000..c88e87f --- /dev/null +++ b/src/test/java/com/jd/jdbc/vitess/VitessJdbcUrlParserTest.java @@ -0,0 +1,123 @@ +/* +Copyright 2021 JD Project Authors. + +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 com.jd.jdbc.vitess; + +import com.jd.jdbc.sqlparser.utils.StringUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import testsuite.TestSuite; +import testsuite.internal.environment.TestSuiteEnv; +import java.net.URI; +import java.net.URISyntaxException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import static com.jd.jdbc.vitess.VitessJdbcUrlParser.JDBC_VITESS_PREFIX; +import static testsuite.internal.TestSuiteShardSpec.TWO_SHARDS; + +public class VitessJdbcUrlParserTest extends TestSuite { + TestSuiteEnv env = Driver.of(TWO_SHARDS); + + String schema = getKeyspace(env); + + String role = "rw"; + + String user = getUser(env); + + String password = getPassword(env); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Connection conn; + + private void init() throws SQLException { + String connecturlionUrl = getConnectionUrl(env); + + URI uri = null; + try { + uri = new URI(connecturlionUrl.substring(JDBC_VITESS_PREFIX.length())); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + String path = uri.getPath(); + connecturlionUrl = connecturlionUrl.replace(path, "/" + schema); + String urlUser = ""; + String urlPasswd = ""; + String urlRole = ""; + String parameters = uri.getQuery(); + parameters = StringUtils.replaceEach(parameters, new String[] {":", " "}, new String[] {"", " "}); + String[] parameterPairs = parameters.split("&"); + for (String parameterPair : parameterPairs) { + String[] pair = parameterPair.trim().split("="); + if (pair.length == 2) { + if (pair[0].equals("user")) { + urlUser = pair[1]; + } else if (pair[0].equals("password")) { + urlPasswd = pair[1]; + } else if (pair[0].equals("role")) { + urlRole = pair[1]; + } + } + } + connecturlionUrl = connecturlionUrl.replace(urlUser, user).replace(urlPasswd, password); + if (!urlRole.equals("")) { + connecturlionUrl = connecturlionUrl.replace(urlRole, role); + } else { + connecturlionUrl += "&role=" + role; + } + + this.conn = DriverManager.getConnection(connecturlionUrl); + try (Statement stmt = this.conn.createStatement()) { + stmt.executeUpdate("delete from plan_test"); + } + } + + @Test + public void testUserParam() throws SQLException { + user = ""; + thrown.expect(SQLException.class); + thrown.expectMessage("no user or password: '/" + schema + "'"); + init(); + } + + @Test + public void testPasswdParam() throws SQLException { + password = ""; + thrown.expect(SQLException.class); + thrown.expectMessage("no user or password: '/" + schema + "'"); + init(); + } + + @Test + public void testSchemaParam() throws SQLException { + schema = ""; + thrown.expect(SQLException.class); + thrown.expectMessage(" database name can not null"); + init(); + } + + @Test + public void testRoleParam() throws SQLException { + role = "aa"; + thrown.expect(SQLException.class); + thrown.expectMessage("'role=" + role + "' " + "error in jdbc url"); + init(); + } +}