Skip to content

Commit 07253ca

Browse files
committed
[#333] Only accept Vert.x style url
1 parent c741fd5 commit 07253ca

22 files changed

+265
-624
lines changed

hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ public interface Log extends BasicLogger {
6464
@Message(id = 18, value = "Instantiating reactive pool: %1$s")
6565
void instantiatingReactivePool(@FormatWith(ClassFormatter.class) Class<?> implClass);
6666

67+
@Message(id = 19, value = "Cannot specify URL using the JDBC syntax. Check the Hibernate Reactive or Vert.x SQL client documentation for more details." +
68+
" Invalid URL: %s")
69+
HibernateException invalidJdbcUrl(String url);
70+
6771
@LogMessage(level = WARN)
6872
@Message(id = 21, value = "DDL command failed [%1$s]")
6973
void ddlCommandFailed(String message);
@@ -253,5 +257,4 @@ public interface Log extends BasicLogger {
253257
@LogMessage(level = WARN)
254258
@Message(id = 447, value= "Explicit use of UPGRADE_SKIPLOCKED in lock() calls is not recommended; use normal UPGRADE locking instead")
255259
void explicitSkipLockedLockCombo();
256-
257260
}

hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPool.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) {
125125

126126
@Override
127127
public void configure(Map configuration) {
128-
uri = jdbcUrl( configuration );
128+
uri = connectionUri( configuration );
129129
}
130130

131131
@Override
@@ -198,7 +198,7 @@ protected Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions
198198
*
199199
* @return the JDBC URL as a {@link URI}
200200
*/
201-
protected URI jdbcUrl(Map<?,?> configurationValues) {
201+
protected URI connectionUri(Map<?,?> configurationValues) {
202202
String url = ConfigurationHelper.getString( Settings.URL, configurationValues );
203203
LOG.sqlClientUrl( url);
204204
return parse( url );
@@ -240,21 +240,15 @@ public void stop() {
240240
}
241241

242242
public static URI parse(String url) {
243-
244243
if ( url == null || url.trim().isEmpty() ) {
245244
throw new HibernateError( "The configuration property '" + Settings.URL + "' was not provided, or is in invalid format. This is required when using the default DefaultSqlClientPool: " +
246245
"either provide the configuration setting or integrate with a different SqlClientPool implementation" );
247246
}
248247

249248
if ( url.startsWith( "jdbc:" ) ) {
250-
return URI.create( updateUrl( url.substring( 5 ) ) );
249+
throw LOG.invalidJdbcUrl( url );
251250
}
252251

253-
return URI.create( updateUrl( url ) );
254-
}
255-
256-
private static String updateUrl(String url) {
257-
return url.replaceAll( "^cockroachdb:", "postgres:" );
252+
return URI.create( url );
258253
}
259-
260254
}

hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java

Lines changed: 8 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.util.Map;
1111
import java.util.concurrent.TimeUnit;
1212

13-
import org.hibernate.HibernateError;
1413
import org.hibernate.reactive.logging.impl.Log;
1514
import org.hibernate.reactive.logging.impl.LoggerFactory;
1615
import org.hibernate.reactive.provider.Settings;
@@ -64,7 +63,6 @@ public void configure(Map configuration) {
6463
@Override
6564
public PoolOptions poolOptions() {
6665
PoolOptions poolOptions = new PoolOptions();
67-
6866
LOG.connectionPoolSize( poolSize );
6967
poolOptions.setMaxSize( poolSize );
7068
if ( maxWaitQueueSize != null ) {
@@ -90,122 +88,23 @@ public PoolOptions poolOptions() {
9088

9189
@Override
9290
public SqlConnectOptions connectOptions(URI uri) {
93-
String scheme = uri.getScheme();
94-
String path = scheme.equals( "oracle" )
95-
? oraclePath( uri )
96-
: uri.getPath();
97-
98-
String database = path.length() > 0
99-
? path.substring( 1 )
100-
: "";
91+
String url = uri.toString().replaceAll( "^cockroachdb:", "postgres:" );
92+
final SqlConnectOptions connectOptions = SqlConnectOptions.fromUri( url );
10193

102-
if ( scheme.equals( "db2" ) && database.indexOf( ':' ) > 0 ) {
103-
// DB2 URLs are a bit odd and have the format:
104-
// jdbc:db2://<HOST>:<PORT>/<DB>:key1=value1;key2=value2;
105-
database = database.substring( 0, database.indexOf( ':' ) );
94+
if ( connectOptions.getUser() == null && user == null ) {
95+
throw new IllegalArgumentException( "database username not specified (set the property 'hibernate.connection.username', or include it as a parameter in the connection URL)" );
10696
}
10797

108-
String host = scheme.equals( "oracle" )
109-
? oracleHost( uri )
110-
: uri.getHost();
111-
112-
int port = scheme.equals( "oracle" )
113-
? oraclePort( uri )
114-
: uri.getPort();
115-
116-
int index = uri.toString().indexOf( ';' );
117-
if ( scheme.equals( "sqlserver" ) && index > 0 ) {
118-
// SQL Server separates parameters in the url with a semicolon (';')
119-
// and the URI class doesn't get the right value for host and port when the url
120-
// contains parameters
121-
URI uriWithoutParams = URI.create( uri.toString().substring( 0, index ) );
122-
host = uriWithoutParams.getHost();
123-
port = uriWithoutParams.getPort();
98+
if ( user != null ) {
99+
connectOptions.setUser( user );
124100
}
125101

126-
if ( port == -1 ) {
127-
port = defaultPort( scheme );
128-
}
129-
130-
//see if the credentials were specified via properties
131-
String username = user;
132-
String password = pass;
133-
if ( username == null || password == null ) {
134-
//if not, look for URI-style user info first
135-
String userInfo = uri.getUserInfo();
136-
if ( userInfo != null ) {
137-
String[] bits = userInfo.split( ":" );
138-
username = bits[0];
139-
if ( bits.length > 1 ) {
140-
password = bits[1];
141-
}
142-
}
143-
else {
144-
//check the query for named parameters
145-
//in case it's a JDBC-style URL
146-
String[] params = {};
147-
// DB2 URLs are a bit odd and have the format:
148-
// jdbc:db2://<HOST>:<PORT>/<DB>:key1=value1;key2=value2;
149-
if ( scheme.equals( "db2" ) ) {
150-
int queryIndex = uri.getPath().indexOf( ':' ) + 1;
151-
if ( queryIndex > 0 ) {
152-
params = uri.getPath().substring( queryIndex ).split( ";" );
153-
}
154-
}
155-
else if ( scheme.contains( "sqlserver" ) ) {
156-
// SQL Server separates parameters in the url with a semicolon (';')
157-
// Ex: jdbc:sqlserver://<server>:<port>;<database>=AdventureWorks;user=<user>;password=<password>
158-
String query = uri.getQuery();
159-
String rawQuery = uri.getRawQuery();
160-
String s = uri.toString();
161-
int queryIndex = s.indexOf( ';' ) + 1;
162-
if ( queryIndex > 0 ) {
163-
params = s.substring( queryIndex ).split( ";" );
164-
}
165-
}
166-
else {
167-
final String query = scheme.equals( "oracle" )
168-
? oracleQuery( uri )
169-
: uri.getQuery();
170-
if ( query != null ) {
171-
params = query.split( "&" );
172-
}
173-
}
174-
for ( String param : params ) {
175-
if ( param.startsWith( "user=" ) ) {
176-
username = param.substring( 5 );
177-
}
178-
else if ( param.startsWith( "pass=" ) ) {
179-
password = param.substring( 5 );
180-
}
181-
else if ( param.startsWith( "password=" ) ) {
182-
password = param.substring( 9 );
183-
}
184-
else if ( param.startsWith( "database=" ) ) {
185-
database = param.substring( 9 );
186-
}
187-
}
188-
}
189-
}
190-
191-
if ( username == null ) {
192-
throw new HibernateError(
193-
"database username not specified (set the property 'javax.persistence.jdbc.user', or include it as a parameter in the connection URL)" );
194-
}
195-
196-
SqlConnectOptions connectOptions = new SqlConnectOptions()
197-
.setHost( host )
198-
.setPort( port )
199-
.setDatabase( database )
200-
.setUser( username );
201-
202-
if ( password != null ) {
203-
connectOptions.setPassword( password );
102+
if ( pass != null ) {
103+
connectOptions.setPassword( pass );
204104
}
205105

206106
//enable the prepared statement cache by default
207107
connectOptions.setCachePreparedStatements( true );
208-
209108
if ( cacheMaxSize != null ) {
210109
if ( cacheMaxSize <= 0 ) {
211110
LOG.preparedStatementCacheDisabled();
@@ -225,86 +124,4 @@ else if ( param.startsWith( "database=" ) ) {
225124

226125
return connectOptions;
227126
}
228-
229-
private int oraclePort(URI uri) {
230-
String s = uri.toString().substring( "oracle:thin:".length() );
231-
if ( s.indexOf( ':' ) > -1 ) {
232-
// Example: localhost:1234...
233-
s = s.substring( s.indexOf( ':' ) + 1 );
234-
if ( s.indexOf( '/' ) != -1 ) {
235-
// Example: 1234/
236-
s = s.substring( 0, s.indexOf( '/' ) );
237-
return Integer.valueOf( s );
238-
}
239-
if ( s.indexOf( '?' ) != -1 ) {
240-
// Example: 1234?param=value
241-
s = s.substring( 0, s.indexOf( '?' ) );
242-
return Integer.valueOf( s );
243-
}
244-
// Example: 1234
245-
return Integer.valueOf( s );
246-
}
247-
return -1;
248-
}
249-
250-
// For Oracle the host part starts with a '@'
251-
// Example oracle:thin:[username/password]@localhost:1234/database?param=value
252-
private String oracleHost(URI uri) {
253-
String s = uri.toString();
254-
String host = s.substring( s.indexOf( '@' ) + 1 );
255-
int end = host.indexOf( ':' );
256-
if ( end == -1 ) {
257-
end = host.indexOf( '/' );
258-
if ( end == -1) {
259-
end = host.indexOf( '?' );
260-
}
261-
}
262-
return host.substring( 0, end );
263-
}
264-
265-
private String oracleQuery(URI uri) {
266-
String string = uri.toString();
267-
int start = string.indexOf( '?' );
268-
return start == -1
269-
? null
270-
: string.substring( start + 1 );
271-
}
272-
273-
private String oraclePath(URI uri) {
274-
String string = uri.toString();
275-
// Remove everything before localhost:port
276-
final int i = string.indexOf( '@' );
277-
string = string.substring( i + 1 );
278-
// Check the start of the path
279-
int start = string.indexOf( '/' );
280-
if ( start == -1) {
281-
return "";
282-
}
283-
int end = string.indexOf( '?' ) == -1
284-
? string.length()
285-
: string.indexOf( '?' );
286-
return string.substring( start, end );
287-
}
288-
289-
private int defaultPort(String scheme) {
290-
switch ( scheme ) {
291-
case "postgresql":
292-
case "postgres":
293-
return 5432;
294-
case "mariadb":
295-
case "mysql":
296-
return 3306;
297-
case "db2":
298-
return 50000;
299-
case "cockroachdb":
300-
return 26257;
301-
case "sqlserver":
302-
return 1433;
303-
case "oracle":
304-
return 1521;
305-
default:
306-
throw new IllegalArgumentException( "Unknown default port for scheme: " + scheme );
307-
}
308-
}
309-
310127
}

hibernate-reactive-core/src/test/java/org/hibernate/reactive/BaseReactiveTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.concurrent.CompletableFuture;
1010
import java.util.concurrent.CompletionStage;
1111
import java.util.concurrent.TimeUnit;
12+
import java.util.function.Supplier;
1213
import java.util.stream.Collectors;
1314

1415
import org.hibernate.SessionFactory;
@@ -119,7 +120,7 @@ public static void test(Async async, TestContext context, Uni<?> uni) {
119120
protected Configuration constructConfiguration() {
120121
Configuration configuration = new Configuration();
121122
configuration.setProperty( Settings.HBM2DDL_AUTO, "create" );
122-
configuration.setProperty( Settings.URL, DatabaseConfiguration.getJdbcUrl() );
123+
configuration.setProperty( Settings.URL, DatabaseConfiguration.getConnectionUri() );
123124
if ( DatabaseConfiguration.dbType() == DBType.DB2 && !doneTablespace ) {
124125
configuration.setProperty(Settings.HBM2DDL_IMPORT_FILES, "/db2.sql");
125126
doneTablespace = true;
@@ -153,17 +154,21 @@ public CompletionStage<Void> deleteEntities(String... entities) {
153154

154155
@Before
155156
public void before(TestContext context) {
156-
test( context, setupSessionFactory( constructConfiguration() ) );
157+
test( context, setupSessionFactory( () -> constructConfiguration() ) );
157158
}
158159

159160
protected CompletionStage<Void> setupSessionFactory(Configuration configuration) {
161+
return setupSessionFactory( () -> configuration );
162+
}
163+
164+
protected CompletionStage<Void> setupSessionFactory(Supplier<Configuration> configurationSupplier) {
160165
CompletableFuture<Void> future = new CompletableFuture<>();
161166
vertxContextRule.vertx()
162167
.executeBlocking(
163168
// schema generation is a blocking operation and so it causes an
164169
// exception when run on the Vert.x event loop. So call it using
165170
// Vertx.executeBlocking()
166-
promise -> startFactoryManager( promise, configuration ),
171+
promise -> startFactoryManager( promise, configurationSupplier.get() ),
167172
event -> {
168173
if ( event.succeeded() ) {
169174
future.complete( null );

0 commit comments

Comments
 (0)