Skip to content

Commit aeb8828

Browse files
committed
Fix for Bug#27652379, NPE FROM GETSESSION(PROPERTIES) WHEN HOST PARAMETER IS GIVEN IN SMALL LETTER.
1 parent ce8167a commit aeb8828

27 files changed

+519
-391
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.0.12
55

6+
- Fix for Bug#27652379, NPE FROM GETSESSION(PROPERTIES) WHEN HOST PARAMETER IS GIVEN IN SMALL LETTER.
7+
68
- Fix for BUG#87600 (26724154), CONNECTOR THROWS 'MALFORMED DATABASE URL' ON NON MYSQL CONNECTION-URLS.
79

810
- Fix for BUG#26089880, GETCONNECTION("MYSQLX://..") RETURNS NON-X PROTOCOL CONNECTION.

src/main/core-api/java/com/mysql/cj/conf/ConnectionUrl.java

Lines changed: 43 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import java.io.InputStream;
3636
import java.sql.DriverManager;
3737
import java.util.ArrayList;
38-
import java.util.Arrays;
3938
import java.util.Collections;
4039
import java.util.HashMap;
4140
import java.util.List;
@@ -47,6 +46,7 @@
4746
import java.util.stream.Collectors;
4847

4948
import com.mysql.cj.Messages;
49+
import com.mysql.cj.conf.PropertyDefinitions.PropertyKey;
5050
import com.mysql.cj.exceptions.CJException;
5151
import com.mysql.cj.exceptions.ExceptionFactory;
5252
import com.mysql.cj.exceptions.InvalidConnectionAttributeException;
@@ -301,11 +301,11 @@ protected ConnectionUrl(ConnectionUrlParser connStrParser, Properties info) {
301301
*/
302302
protected void collectProperties(ConnectionUrlParser connStrParser, Properties info) {
303303
// Fill in the properties from the connection string.
304-
this.properties.putAll(connStrParser.getProperties());
304+
connStrParser.getProperties().entrySet().stream().forEach(e -> this.properties.put(PropertyKey.normalizeCase(e.getKey()), e.getValue()));
305305

306306
// Properties passed in override the ones from the connection string.
307307
if (info != null) {
308-
info.stringPropertyNames().stream().forEach(k -> this.properties.put(k, info.getProperty(k)));
308+
info.stringPropertyNames().stream().forEach(k -> this.properties.put(PropertyKey.normalizeCase(k), info.getProperty(k)));
309309
}
310310

311311
// Collect properties from additional sources.
@@ -360,7 +360,8 @@ protected void expandPropertiesFromConfigFiles(Map<String, String> props) {
360360
String configFiles = props.get(PropertyDefinitions.PNAME_useConfigs);
361361
if (!isNullOrEmpty(configFiles)) {
362362
Properties configProps = getPropertiesFromConfigFiles(configFiles);
363-
configProps.stringPropertyNames().stream().filter(k -> !props.containsKey(k)).forEach(k -> props.put(k, configProps.getProperty(k)));
363+
configProps.stringPropertyNames().stream().map(PropertyKey::normalizeCase).filter(k -> !props.containsKey(k))
364+
.forEach(k -> props.put(k, configProps.getProperty(k)));
364365
}
365366
}
366367

@@ -417,44 +418,47 @@ protected void collectHostsInfo(ConnectionUrlParser connStrParser) {
417418
* @return a new {@link HostInfo} with all required data
418419
*/
419420
protected HostInfo fixHostInfo(HostInfo hi) {
420-
Map<String, String> hostProps = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
421+
Map<String, String> hostProps = new HashMap<>();
421422

422-
hostProps.putAll(this.properties); // Add global connection arguments.
423-
hostProps.putAll(hi.getHostProperties()); // Add/override host specific connection arguments.
424-
hostProps.put(PropertyDefinitions.DBNAME_PROPERTY_KEY, getDatabase()); // Add the database name
423+
// Add global connection arguments.
424+
hostProps.putAll(this.properties);
425+
// Add/override host specific connection arguments.
426+
hi.getHostProperties().entrySet().stream().forEach(e -> hostProps.put(PropertyKey.normalizeCase(e.getKey()), e.getValue()));
427+
// Add the database name
428+
hostProps.put(PropertyKey.DBNAME.getKeyName(), getDatabase());
425429

426-
hostProps = preprocessPerTypeHostProperties(hostProps);
430+
preprocessPerTypeHostProperties(hostProps);
427431

428-
String host = hostProps.remove(PropertyDefinitions.HOST_PROPERTY_KEY);
432+
String host = hostProps.remove(PropertyKey.HOST.getKeyName());
429433
if (!isNullOrEmpty(hi.getHost())) {
430434
host = hi.getHost();
431435
} else if (isNullOrEmpty(host)) {
432436
host = getDefaultHost();
433437
}
434438

435-
String portAsString = hostProps.remove(PropertyDefinitions.PORT_PROPERTY_KEY);
439+
String portAsString = hostProps.remove(PropertyKey.PORT.getKeyName());
436440
int port = hi.getPort();
437441
if (port == -1 && !isNullOrEmpty(portAsString)) {
438442
try {
439443
port = Integer.valueOf(portAsString);
440444
} catch (NumberFormatException e) {
441445
throw ExceptionFactory.createException(WrongArgumentException.class,
442-
Messages.getString("ConnectionString.7", new Object[] { hostProps.get(PropertyDefinitions.PORT_PROPERTY_KEY) }), e);
446+
Messages.getString("ConnectionString.7", new Object[] { hostProps.get(PropertyKey.PORT.getKeyName()) }), e);
443447
}
444448
}
445449
if (port == -1) {
446450
port = getDefaultPort();
447451
}
448452

449-
String user = hostProps.remove(PropertyDefinitions.PNAME_user);
453+
String user = hostProps.remove(PropertyKey.USER.getKeyName());
450454
if (!isNullOrEmpty(hi.getUser())) {
451455
user = hi.getUser();
452456
} else if (isNullOrEmpty(user)) {
453457
user = getDefaultUser();
454458
}
455459

456460
boolean isPasswordless = hi.isPasswordless();
457-
String password = hostProps.remove(PropertyDefinitions.PNAME_password);
461+
String password = hostProps.remove(PropertyKey.PASSWORD.getKeyName());
458462
if (!isPasswordless) {
459463
password = hi.getPassword();
460464
} else if (password == null) {
@@ -465,7 +469,6 @@ protected HostInfo fixHostInfo(HostInfo hi) {
465469
}
466470

467471
expandPropertiesFromConfigFiles(hostProps);
468-
fixKeysCase(hostProps);
469472
fixProtocolDependencies(hostProps);
470473

471474
return buildHostInfo(host, port, user, password, isPasswordless, hostProps);
@@ -479,8 +482,8 @@ protected HostInfo fixHostInfo(HostInfo hi) {
479482
* @return
480483
* the processed host properties map
481484
*/
482-
protected Map<String, String> preprocessPerTypeHostProperties(Map<String, String> hostProps) {
483-
return hostProps;
485+
protected void preprocessPerTypeHostProperties(Map<String, String> hostProps) {
486+
// To be overridden in subclasses if needed.
484487
}
485488

486489
/**
@@ -507,7 +510,7 @@ public int getDefaultPort() {
507510
* @return the default user
508511
*/
509512
public String getDefaultUser() {
510-
String user = this.properties.get(PropertyDefinitions.PNAME_user);
513+
String user = this.properties.get(PropertyKey.USER.getKeyName());
511514
return isNullOrEmpty(user) ? "" : user;
512515
}
513516

@@ -518,39 +521,24 @@ public String getDefaultUser() {
518521
* @return the default password
519522
*/
520523
public String getDefaultPassword() {
521-
String password = this.properties.get(PropertyDefinitions.PNAME_password);
524+
String password = this.properties.get(PropertyKey.PASSWORD.getKeyName());
522525
return isNullOrEmpty(password) ? "" : password;
523526
}
524527

525-
/**
526-
* Fixes the case for alternate host syntax main properties.
527-
*
528-
* @param hostProps
529-
* the host properties map to fix
530-
*/
531-
protected void fixKeysCase(Map<String, String> hostProps) {
532-
for (String key : Arrays.asList(PropertyDefinitions.PROTOCOL_PROPERTY_KEY, PropertyDefinitions.PATH_PROPERTY_KEY, PropertyDefinitions.TYPE_PROPERTY_KEY,
533-
PropertyDefinitions.ADDRESS_PROPERTY_KEY, PropertyDefinitions.PRIORITY_PROPERTY_KEY)) {
534-
if (hostProps.containsKey(key)) {
535-
hostProps.put(key, hostProps.remove(key));
536-
}
537-
}
538-
}
539-
540528
/**
541529
* Fixes the protocol (TCP vs PIPE) dependencies for the given host properties map.
542530
*
543531
* @param hostProps
544532
* the host properties map to fix
545533
*/
546534
protected void fixProtocolDependencies(Map<String, String> hostProps) {
547-
String protocol = hostProps.get(PropertyDefinitions.PROTOCOL_PROPERTY_KEY);
535+
String protocol = hostProps.get(PropertyKey.PROTOCOL.getKeyName());
548536
if (!isNullOrEmpty(protocol) && protocol.equalsIgnoreCase("PIPE")) {
549537
if (!hostProps.containsKey(PropertyDefinitions.PNAME_socketFactory)) {
550538
hostProps.put(PropertyDefinitions.PNAME_socketFactory, "com.mysql.cj.protocol.NamedPipeSocketFactory");
551539
}
552-
if (hostProps.containsKey(PropertyDefinitions.PATH_PROPERTY_KEY) && !hostProps.containsKey(PropertyDefinitions.NAMED_PIPE_PROP_NAME)) {
553-
hostProps.put(PropertyDefinitions.NAMED_PIPE_PROP_NAME, hostProps.get(PropertyDefinitions.PATH_PROPERTY_KEY));
540+
if (hostProps.containsKey(PropertyKey.PATH.getKeyName()) && !hostProps.containsKey(PropertyDefinitions.NAMED_PIPE_PROP_NAME)) {
541+
hostProps.put(PropertyDefinitions.NAMED_PIPE_PROP_NAME, hostProps.get(PropertyKey.PATH.getKeyName()));
554542
}
555543
}
556544
}
@@ -580,8 +568,7 @@ public String getDatabaseUrl() {
580568
* @return the database name
581569
*/
582570
public String getDatabase() {
583-
return this.properties.containsKey(PropertyDefinitions.DBNAME_PROPERTY_KEY) ? this.properties.get(PropertyDefinitions.DBNAME_PROPERTY_KEY)
584-
: this.originalDatabase;
571+
return this.properties.containsKey(PropertyKey.DBNAME.getKeyName()) ? this.properties.get(PropertyKey.DBNAME.getKeyName()) : this.originalDatabase;
585572
}
586573

587574
/**
@@ -671,30 +658,31 @@ private HostInfo buildHostInfo(String host, int port, String user, String passwo
671658
Properties props = new Properties();
672659
props.putAll(hostProps);
673660

674-
props.setProperty(PropertyDefinitions.HOST_PROPERTY_KEY, host);
675-
props.setProperty(PropertyDefinitions.PORT_PROPERTY_KEY, String.valueOf(port));
676-
props.setProperty(PropertyDefinitions.PNAME_user, user);
677-
props.setProperty(PropertyDefinitions.PNAME_password, password);
661+
props.setProperty(PropertyKey.HOST.getKeyName(), host);
662+
props.setProperty(PropertyKey.PORT.getKeyName(), String.valueOf(port));
663+
props.setProperty(PropertyKey.USER.getKeyName(), user);
664+
props.setProperty(PropertyKey.PASSWORD.getKeyName(), password);
678665

679666
Properties transformedProps = this.propertiesTransformer.transformProperties(props);
680667

681-
host = transformedProps.getProperty(PropertyDefinitions.HOST_PROPERTY_KEY);
668+
host = transformedProps.getProperty(PropertyKey.PORT.getKeyName());
682669
try {
683-
port = Integer.parseInt(transformedProps.getProperty(PropertyDefinitions.PORT_PROPERTY_KEY));
670+
port = Integer.parseInt(transformedProps.getProperty(PropertyKey.PORT.getKeyName()));
684671
} catch (NumberFormatException e) {
685-
throw ExceptionFactory.createException(WrongArgumentException.class,
686-
Messages.getString("ConnectionString.8",
687-
new Object[] { PropertyDefinitions.PORT_PROPERTY_KEY, transformedProps.getProperty(PropertyDefinitions.PORT_PROPERTY_KEY) }),
688-
e);
672+
throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("ConnectionString.8",
673+
new Object[] { PropertyKey.PORT.getKeyName(), transformedProps.getProperty(PropertyKey.PORT.getKeyName()) }), e);
689674
}
690-
user = transformedProps.getProperty(PropertyDefinitions.PNAME_user);
691-
password = transformedProps.getProperty(PropertyDefinitions.PNAME_password);
675+
user = transformedProps.getProperty(PropertyKey.USER.getKeyName());
676+
password = transformedProps.getProperty(PropertyKey.PASSWORD.getKeyName());
692677

693-
List<String> surplusKeys = Arrays.asList(PropertyDefinitions.HOST_PROPERTY_KEY, PropertyDefinitions.PORT_PROPERTY_KEY,
694-
PropertyDefinitions.PNAME_user, PropertyDefinitions.PNAME_password);
695678
Map<String, String> transformedHostProps = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
696-
transformedProps.stringPropertyNames().stream().filter(k -> !surplusKeys.contains(k))
697-
.forEach(k -> transformedHostProps.put(k, transformedProps.getProperty(k)));
679+
transformedProps.stringPropertyNames().stream().forEach(k -> transformedHostProps.put(k, transformedProps.getProperty(k)));
680+
// Remove surplus keys.
681+
transformedHostProps.remove(PropertyKey.HOST.getKeyName());
682+
transformedHostProps.remove(PropertyKey.PORT.getKeyName());
683+
transformedHostProps.remove(PropertyKey.USER.getKeyName());
684+
transformedHostProps.remove(PropertyKey.PASSWORD.getKeyName());
685+
698686
hostProps = transformedHostProps;
699687
}
700688

src/main/core-api/java/com/mysql/cj/conf/HostInfo.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
package com.mysql.cj.conf;
3131

32-
import static com.mysql.cj.conf.PropertyDefinitions.DBNAME_PROPERTY_KEY;
3332
import static com.mysql.cj.util.StringUtils.isNullOrEmpty;
3433

3534
import java.util.Collections;
@@ -38,6 +37,8 @@
3837
import java.util.Map;
3938
import java.util.Properties;
4039

40+
import com.mysql.cj.conf.PropertyDefinitions.PropertyKey;
41+
4142
/**
4243
* This class holds the following MySQL host information:
4344
* <ul>
@@ -133,12 +134,19 @@ public HostInfo(DatabaseUrlContainer url, String host, int port, String user, St
133134
}
134135
}
135136

137+
/**
138+
* Constructs a {@link HostInfo} instance initialized with the provided properties.
139+
*
140+
* @param properties
141+
* a connection arguments map.
142+
*/
136143
public HostInfo(Properties props) {
137144
this.originalUrl = null;
138-
this.host = props.getProperty(PropertyDefinitions.HOST_PROPERTY_KEY);
139-
this.port = Integer.parseInt(props.getProperty(PropertyDefinitions.PORT_PROPERTY_KEY));
140-
this.user = props.getProperty(PropertyDefinitions.PNAME_user);
141-
this.password = props.getProperty(PropertyDefinitions.PNAME_password);
145+
146+
this.host = props.getProperty(PropertyKey.HOST.getKeyName());
147+
this.port = Integer.parseInt(props.getProperty(PropertyKey.PORT.getKeyName()));
148+
this.user = props.getProperty(PropertyKey.USER.getKeyName());
149+
this.password = props.getProperty(PropertyKey.PASSWORD.getKeyName());
142150
this.isPasswordless = this.password == null;
143151
Enumeration<Object> keyEnum = props.keys();
144152
while (keyEnum.hasMoreElements()) {
@@ -229,7 +237,7 @@ public String getProperty(String key) {
229237
* @return the database name
230238
*/
231239
public String getDatabase() {
232-
String database = this.hostProperties.get(DBNAME_PROPERTY_KEY);
240+
String database = this.hostProperties.get(PropertyKey.DBNAME.getKeyName());
233241
return isNullOrEmpty(database) ? "" : database;
234242
}
235243

@@ -242,10 +250,10 @@ public String getDatabase() {
242250
public Properties exposeAsProperties() {
243251
Properties props = new Properties();
244252
this.hostProperties.entrySet().stream().forEach(e -> props.setProperty(e.getKey(), e.getValue() == null ? "" : e.getValue()));
245-
props.setProperty(PropertyDefinitions.HOST_PROPERTY_KEY, getHost());
246-
props.setProperty(PropertyDefinitions.PORT_PROPERTY_KEY, String.valueOf(getPort()));
247-
props.setProperty(PropertyDefinitions.PNAME_user, getUser());
248-
props.setProperty(PropertyDefinitions.PNAME_password, getPassword());
253+
props.setProperty(PropertyKey.HOST.getKeyName(), getHost());
254+
props.setProperty(PropertyKey.PORT.getKeyName(), String.valueOf(getPort()));
255+
props.setProperty(PropertyKey.USER.getKeyName(), getUser());
256+
props.setProperty(PropertyKey.PASSWORD.getKeyName(), getPassword());
249257
return props;
250258
}
251259

0 commit comments

Comments
 (0)