Merge pull request #37 from scottfrederick/query
Changed JDBC URL creation to retain query parameters.
This commit is contained in:
@@ -67,7 +67,12 @@ public abstract class UriBasedServiceInfo extends BaseServiceInfo {
|
||||
public String getPath() {
|
||||
return uriInfo.getPath();
|
||||
}
|
||||
|
||||
|
||||
@ServiceProperty(category="connection")
|
||||
public String getQuery() {
|
||||
return uriInfo.getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the URI and clean it up by using defaults for any missing information, if possible.
|
||||
*
|
||||
|
||||
@@ -3,29 +3,48 @@ package org.springframework.cloud.service.common;
|
||||
import org.springframework.cloud.service.UriBasedServiceInfo;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
*
|
||||
*/
|
||||
public abstract class RelationalServiceInfo extends UriBasedServiceInfo {
|
||||
|
||||
protected String jdbcUrlDatabaseType;
|
||||
protected String jdbcUrlDatabaseType;
|
||||
|
||||
public RelationalServiceInfo(String id, String uriString, String jdbcUrlDatabaseType) {
|
||||
super(id, uriString);
|
||||
this.jdbcUrlDatabaseType = jdbcUrlDatabaseType;
|
||||
}
|
||||
public RelationalServiceInfo(String id, String uriString, String jdbcUrlDatabaseType) {
|
||||
super(id, uriString);
|
||||
this.jdbcUrlDatabaseType = jdbcUrlDatabaseType;
|
||||
}
|
||||
|
||||
@ServiceProperty(category="connection")
|
||||
public String getJdbcUrl() {
|
||||
if (getPort() != -1) {
|
||||
return String.format("jdbc:%s://%s:%d/%s?user=%s&password=%s",
|
||||
jdbcUrlDatabaseType, getHost(), getPort(), getPath(),
|
||||
getUserName(), getPassword());
|
||||
} else {
|
||||
return String.format("jdbc:%s://%s/%s?user=%s&password=%s",
|
||||
jdbcUrlDatabaseType, getHost(), getPath(),
|
||||
getUserName(), getPassword());
|
||||
}
|
||||
}
|
||||
@ServiceProperty(category = "connection")
|
||||
public String getJdbcUrl() {
|
||||
return String.format("jdbc:%s://%s%s/%s%s%s", jdbcUrlDatabaseType, getHost(), formatPort(),
|
||||
getPath(), formatUserinfo(), formatQuery());
|
||||
}
|
||||
|
||||
private String formatPort() {
|
||||
if (getPort() != -1) {
|
||||
return String.format(":%d", getPort());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String formatUserinfo() {
|
||||
if (getUserName() != null && getPassword() != null) {
|
||||
return String.format("?user=%s&password=%s", getUserName(), getPassword());
|
||||
}
|
||||
if (getUserName() != null) {
|
||||
return String.format("?user=%s", getUserName());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String formatQuery() {
|
||||
if (getQuery() != null) {
|
||||
if (getUserName() == null && getPassword() == null) {
|
||||
return String.format("?%s", getQuery());
|
||||
} else {
|
||||
return String.format("&%s", getQuery());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,64 +6,83 @@ import java.net.URLDecoder;
|
||||
|
||||
/**
|
||||
* Factory for standard Cloud Foundry URIs which all conform to the format:
|
||||
*
|
||||
* [jdbc:]scheme://[user:pass]@authority/path
|
||||
* <p/>
|
||||
* [jdbc:]scheme://[user:pass]@authority[:port]/path
|
||||
*/
|
||||
public class StandardUriInfoFactory implements UriInfoFactory {
|
||||
@Override
|
||||
public UriInfo createUri(String uriString) {
|
||||
String userName = null;
|
||||
String password = null;
|
||||
String path;
|
||||
URI tmpUri;
|
||||
|
||||
if (uriString.startsWith("jdbc:")) {
|
||||
int idx = uriString.indexOf(":");
|
||||
uriString = uriString.substring(idx + 1);
|
||||
}
|
||||
public static final String JDBC_PREFIX = "jdbc:";
|
||||
|
||||
try {
|
||||
tmpUri = new URI(uriString);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
@Override
|
||||
public UriInfo createUri(String scheme, String host, int port, String username, String password, String path) {
|
||||
return new UriInfo(scheme, host, port, username, password, path);
|
||||
}
|
||||
|
||||
String userInfo = tmpUri.getRawUserInfo();
|
||||
if (userInfo != null) {
|
||||
String userPass[] = userInfo.split(":");
|
||||
if (userPass.length != 2) {
|
||||
throw new IllegalArgumentException("bad user info in URI: " + tmpUri);
|
||||
}
|
||||
@Override
|
||||
public UriInfo createUri(String uriString) {
|
||||
|
||||
userName = uriDecode(userPass[0]);
|
||||
password = uriDecode(userPass[1]);
|
||||
}
|
||||
uriString = trimJdbcScheme(uriString);
|
||||
|
||||
String rawPath = tmpUri.getRawPath();
|
||||
if (rawPath != null && rawPath.length() > 1) {
|
||||
path = rawPath.substring(1);
|
||||
}
|
||||
else {
|
||||
path = null;
|
||||
}
|
||||
return new UriInfo(tmpUri.getScheme(), tmpUri.getHost(), tmpUri.getPort(), userName, password, path);
|
||||
}
|
||||
URI tmpUri = createTmpUri(uriString);
|
||||
|
||||
@Override
|
||||
public UriInfo createUri(String scheme, String host, int port, String username, String password, String path) {
|
||||
return new UriInfo(scheme, host, port, username, password, path);
|
||||
}
|
||||
String[] userInfo = parseUserinfo(tmpUri);
|
||||
String userName = uriDecode(userInfo[0]);
|
||||
String password = uriDecode(userInfo[1]);
|
||||
|
||||
private static String uriDecode(String s) {
|
||||
try {
|
||||
// URLDecode decodes '+' to a space, as for
|
||||
// form encoding. So protect plus signs.
|
||||
return URLDecoder.decode(s.replace("+", "%2B"), "US-ASCII");
|
||||
}
|
||||
catch (java.io.UnsupportedEncodingException e) {
|
||||
// US-ASCII is always supported
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return new UriInfo(tmpUri.getScheme(), tmpUri.getHost(), tmpUri.getPort(),
|
||||
userName, password,
|
||||
parsePath(tmpUri), tmpUri.getRawQuery());
|
||||
}
|
||||
|
||||
private URI createTmpUri(String uriString) {
|
||||
try {
|
||||
return new URI(uriString);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String trimJdbcScheme(String uriString) {
|
||||
if (uriString.startsWith(JDBC_PREFIX)) {
|
||||
uriString = uriString.substring(JDBC_PREFIX.length());
|
||||
}
|
||||
return uriString;
|
||||
}
|
||||
|
||||
private String[] parseUserinfo(URI uri) {
|
||||
String userInfo = uri.getRawUserInfo();
|
||||
|
||||
if (userInfo != null) {
|
||||
String[] userPass = userInfo.split(":");
|
||||
if (userPass.length != 2) {
|
||||
throw new IllegalArgumentException("Bad userinfo in URI: " + uri);
|
||||
}
|
||||
return userPass;
|
||||
}
|
||||
|
||||
return new String[]{null, null};
|
||||
}
|
||||
|
||||
private String parsePath(URI uri) {
|
||||
String rawPath = uri.getRawPath();
|
||||
if (rawPath != null && rawPath.length() > 1) {
|
||||
return rawPath.substring(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String uriDecode(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// URLDecode decodes '+' to a space, as for
|
||||
// form encoding. So protect plus signs.
|
||||
return URLDecoder.decode(s.replace("+", "%2B"), "US-ASCII");
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
// US-ASCII is always supported
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,22 +17,28 @@ public class UriInfo {
|
||||
private String password;
|
||||
private String path;
|
||||
private URI uri;
|
||||
private String query;
|
||||
|
||||
public UriInfo(String scheme, String host, int port, String username, String password) {
|
||||
this(scheme, host, port, username, password, "");
|
||||
}
|
||||
|
||||
public UriInfo(String scheme, String host, int port, String username, String password, String path) {
|
||||
this(scheme, host, port, username, password, path, null);
|
||||
}
|
||||
|
||||
public UriInfo(String scheme, String host, int port, String username, String password, String path, String query) {
|
||||
this.scheme = scheme;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.userName = username;
|
||||
this.password = password;
|
||||
this.path = path;
|
||||
this.query = query;
|
||||
|
||||
this.uri = buildUri();
|
||||
}
|
||||
|
||||
public UriInfo(String scheme, String host, int port, String username, String password) {
|
||||
this(scheme, host, port, username, password, "");
|
||||
}
|
||||
|
||||
public String getScheme() {
|
||||
return scheme;
|
||||
}
|
||||
@@ -57,11 +63,15 @@ public class UriInfo {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public URI buildUri() throws IllegalArgumentException {
|
||||
private URI buildUri() {
|
||||
String userInfo = null;
|
||||
|
||||
if (userName != null && password != null) {
|
||||
@@ -71,7 +81,7 @@ public class UriInfo {
|
||||
String cleanedPath = path == null || path.startsWith("/") ? path : "/" + path;
|
||||
|
||||
try {
|
||||
return new URI(scheme, userInfo, host, port, cleanedPath, null, null);
|
||||
return new URI(scheme, userInfo, host, port, cleanedPath, query, null);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
|
||||
@@ -5,86 +5,72 @@ import org.springframework.cloud.util.StandardUriInfoFactory;
|
||||
import org.springframework.cloud.util.UriInfo;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Jens Deppe
|
||||
*/
|
||||
public class StandardUriInfoFactoryTest {
|
||||
|
||||
private static StandardUriInfoFactory factory = new StandardUriInfoFactory();
|
||||
private static StandardUriInfoFactory factory = new StandardUriInfoFactory();
|
||||
|
||||
/**
|
||||
* Basic sanity
|
||||
*/
|
||||
@Test
|
||||
public void createUri1() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri(uri);
|
||||
@Test
|
||||
public void createUri() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri(uri);
|
||||
|
||||
assertEquals("localhost", result.getHost());
|
||||
assertEquals(1527, result.getPort());
|
||||
assertEquals("joe", result.getUserName());
|
||||
assertEquals("joes_password", result.getPassword());
|
||||
assertEquals("big_db", result.getPath());
|
||||
assertEquals(uri, result.buildUri().toString());
|
||||
}
|
||||
assertUriInfoEquals(result, "localhost", 1527, "joe", "joes_password", "big_db", null);
|
||||
assertEquals(uri, result.getUri().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with a 'jdbc:...' URI
|
||||
*/
|
||||
@Test
|
||||
public void createUri2() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
|
||||
String jdbcUri = "jdbc:" + uri;
|
||||
UriInfo result = factory.createUri(jdbcUri);
|
||||
@Test
|
||||
public void createUriWithQuery() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db?p1=v1&p2=v2";
|
||||
UriInfo result = factory.createUri(uri);
|
||||
|
||||
assertEquals("localhost", result.getHost());
|
||||
assertEquals(1527, result.getPort());
|
||||
assertEquals("joe", result.getUserName());
|
||||
assertEquals("joes_password", result.getPassword());
|
||||
assertEquals("big_db", result.getPath());
|
||||
assertEquals(uri, result.buildUri().toString());
|
||||
}
|
||||
assertUriInfoEquals(result, "localhost", 1527, "joe", "joes_password", "big_db", "p1=v1&p2=v2");
|
||||
assertEquals(uri, result.getUri().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test without user/password
|
||||
*/
|
||||
@Test
|
||||
public void createUri3() {
|
||||
String uri = "mysql://localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri(uri);
|
||||
@Test
|
||||
public void createWithJdbcUri() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri("jdbc:" + uri);
|
||||
|
||||
assertEquals("localhost", result.getHost());
|
||||
assertEquals(1527, result.getPort());
|
||||
assertNull(result.getUserName());
|
||||
assertNull(result.getPassword());
|
||||
assertEquals("big_db", result.getPath());
|
||||
assertEquals(uri, result.buildUri().toString());
|
||||
}
|
||||
assertUriInfoEquals(result, "localhost", 1527, "joe", "joes_password", "big_db", null);
|
||||
assertEquals(uri, result.getUri().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with just a user and no password
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createUri4() {
|
||||
String uri = "mysql://joe@localhost:1527/big_db";
|
||||
factory.createUri(uri);
|
||||
}
|
||||
@Test
|
||||
public void createNoUsernamePassword() {
|
||||
String uri = "mysql://localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri(uri);
|
||||
|
||||
/**
|
||||
* Test when creating URI with explicit components
|
||||
*/
|
||||
@Test
|
||||
public void createUri5() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri("mysql", "localhost", 1527, "joe", "joes_password", "big_db");
|
||||
assertUriInfoEquals(result, "localhost", 1527, null, null, "big_db", null);
|
||||
assertEquals(uri, result.getUri().toString());
|
||||
}
|
||||
|
||||
assertEquals("localhost", result.getHost());
|
||||
assertEquals(1527, result.getPort());
|
||||
assertEquals("joe", result.getUserName());
|
||||
assertEquals("joes_password", result.getPassword());
|
||||
assertEquals("big_db", result.getPath());
|
||||
assertEquals(uri, result.buildUri().toString());
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createWithUsernameNoPassword() {
|
||||
String uri = "mysql://joe@localhost:1527/big_db";
|
||||
factory.createUri(uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithExplicitParameters() {
|
||||
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
|
||||
UriInfo result = factory.createUri("mysql", "localhost", 1527, "joe", "joes_password", "big_db");
|
||||
|
||||
assertUriInfoEquals(result, "localhost", 1527, "joe", "joes_password", "big_db", null);
|
||||
assertEquals(uri, result.getUri().toString());
|
||||
}
|
||||
|
||||
private void assertUriInfoEquals(UriInfo result, String host, int port,
|
||||
String username, String password, String path, String query) {
|
||||
assertEquals(host, result.getHost());
|
||||
assertEquals(port, result.getPort());
|
||||
assertEquals(username, result.getUserName());
|
||||
assertEquals(password, result.getPassword());
|
||||
assertEquals(path, result.getPath());
|
||||
assertEquals(query, result.getQuery());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.springframework.cloud.service.common;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class RelationalServiceInfoTest {
|
||||
|
||||
@Test
|
||||
public void jdbcFullUrl() {
|
||||
RelationalServiceInfo serviceInfo = createServiceInfo("dbtype://username:password@hostname:1234/database");
|
||||
|
||||
assertEquals("jdbc:jdbcdbtype://hostname:1234/database?user=username&password=password", serviceInfo.getJdbcUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jdbcUrlNoPort() {
|
||||
RelationalServiceInfo serviceInfo = createServiceInfo("dbtype://username:password@hostname/database");
|
||||
|
||||
assertEquals("jdbc:jdbcdbtype://hostname/database?user=username&password=password", serviceInfo.getJdbcUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jdbcUrlNoUsernamePassword() {
|
||||
RelationalServiceInfo serviceInfo = createServiceInfo("dbtype://hostname:1234/database");
|
||||
|
||||
assertEquals("jdbc:jdbcdbtype://hostname:1234/database", serviceInfo.getJdbcUrl());
|
||||
}
|
||||
|
||||
@Test(expected = java.lang.IllegalArgumentException.class)
|
||||
public void jdbcUrlNoPassword() {
|
||||
createServiceInfo("dbtype://username@hostname/database");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jdbcUrlWithQuery() {
|
||||
RelationalServiceInfo serviceInfo = createServiceInfo("dbtype://username:password@hostname:1234/database?reconnect=true");
|
||||
|
||||
assertEquals("jdbc:jdbcdbtype://hostname:1234/database?user=username&password=password&reconnect=true", serviceInfo.getJdbcUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jdbcUrlWithQueryNoUsernamePassword() {
|
||||
RelationalServiceInfo serviceInfo = createServiceInfo("dbtype://hostname:1234/database?reconnect=true");
|
||||
|
||||
assertEquals("jdbc:jdbcdbtype://hostname:1234/database?reconnect=true", serviceInfo.getJdbcUrl());
|
||||
}
|
||||
|
||||
private RelationalServiceInfo createServiceInfo(final String uri) {
|
||||
return new RelationalServiceInfo("test", uri, "jdbcdbtype") {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user