From be1ad5dff30bb42a8266d40bd9b6ddb760f1897b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 26 Aug 2021 17:58:32 -0700 Subject: [PATCH] GUACAMOLE-1407: Automatically detect whether MySQL or MariaDB version of "Connector/J" is installed. --- .../guacamole/auth/jdbc/JDBCEnvironment.java | 20 ++++++++++ .../auth/mysql/conf/MySQLDriver.java | 33 +++++++++++++++- .../auth/mysql/conf/MySQLEnvironment.java | 39 +++++++++++++++---- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java index a6313a965..19544447d 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java @@ -192,4 +192,24 @@ public abstract class JDBCEnvironment extends DelegatingEnvironment { */ public abstract String getPassword() throws GuacamoleException; + /** + * Returns whether the given Java class is defined within the classpath. + * + * @param classname + * The name of the Java class to check. + * + * @return + * true if the given Java class is present within the classpath, false + * otherwise. + */ + public static boolean isClassDefined(String classname) { + try { + Class.forName(classname, false, JDBCEnvironment.class.getClassLoader()); + return true; + } + catch (ClassNotFoundException e) { + return false; + } + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java index 36e8e9b1b..7ce915ab3 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java @@ -19,6 +19,7 @@ package org.apache.guacamole.auth.mysql.conf; +import org.apache.guacamole.auth.jdbc.JDBCEnvironment; import org.apache.guacamole.properties.EnumGuacamoleProperty.PropertyValue; /** @@ -31,11 +32,39 @@ public enum MySQLDriver { * MySQL driver. */ @PropertyValue("mysql") - MYSQL, + MYSQL("com.mysql.jdbc.Driver"), /** * MariaDB driver. */ @PropertyValue("mariadb") - MARIADB; + MARIADB("org.mariadb.jdbc.Driver"); + + /** + * The name of the JDBC driver class. + */ + private final String driverClass; + + /** + * Creates a new MySQLDriver that points to the given Java class as the + * entrypoint of the JDBC driver. + * + * @param classname + * The name of the JDBC driver class. + */ + private MySQLDriver(String classname) { + this.driverClass = classname; + } + + /** + * Returns whether this MySQL JDBC driver is installed and can be found + * within the Java classpath. + * + * @return + * true if this MySQL JDBC driver is installed, false otherwise. + */ + public boolean isInstalled() { + return JDBCEnvironment.isClassDefined(driverClass); + } + } \ No newline at end of file diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java index f4aa645b1..9469b1baf 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java @@ -54,9 +54,10 @@ public class MySQLEnvironment extends JDBCEnvironment { private static final MySQLVersion MYSQL_SUPPORTS_CTE = new MySQLVersion(8, 0, 1, false); /** - * The default MySQL-compatible driver to use, if not specified. + * The default MySQL-compatible driver to use, if not specified and not + * automatically detected. */ - private static final MySQLDriver DEFAULT_DRIVER = MySQLDriver.MYSQL; + private static final MySQLDriver FALLBACK_DEFAULT_DRIVER = MySQLDriver.MYSQL; /** * The default host to connect to, if MYSQL_HOSTNAME is not specified. @@ -178,8 +179,10 @@ public class MySQLEnvironment extends JDBCEnvironment { /** * Returns the MySQL driver that will be used to talk to the MySQL-compatible - * database server hosting the Guacamole Client database. If unspecified - * a default value of MySQL will be used. + * database server hosting the Guacamole database. If unspecified, the + * installed MySQL driver will be automatically detected by inspecting the + * classes available in the classpath. If automatic detection fails, the + * "MySQL Connector/J" driver will be assumed. * * @return * The MySQL driver that will be used to communicate with the MySQL- @@ -189,10 +192,30 @@ public class MySQLEnvironment extends JDBCEnvironment { * If guacamole.properties cannot be parsed. */ public MySQLDriver getMySQLDriver() throws GuacamoleException { - return getProperty( - MySQLGuacamoleProperties.MYSQL_DRIVER, - DEFAULT_DRIVER - ); + + // Use any explicitly-specified driver + MySQLDriver driver = getProperty(MySQLGuacamoleProperties.MYSQL_DRIVER); + if (driver != null) + return driver; + + // Attempt autodetection based on presence of JDBC driver within + // classpath... + + if (MySQLDriver.MARIADB.isInstalled()) { + logger.info("Installed JDBC driver for MySQL/MariaDB detected as \"MariaDB Connector/J\"."); + return MySQLDriver.MARIADB; + } + + if (MySQLDriver.MYSQL.isInstalled()) { + logger.info("Installed JDBC driver for MySQL/MariaDB detected as \"MySQL Connector/J\"."); + return MySQLDriver.MYSQL; + } + + // Fallback to MySQL Connector/J if nothing can be found + logger.warn("JDBC driver for MySQL/MariaDB couuld not be detected " + + "and might not be installed. Assuming MySQL Connector/J..."); + return FALLBACK_DEFAULT_DRIVER; + } /**