/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * 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 org.jkiss.dbeaver.ext.mysql; import org.jkiss.code.NotNull; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.core.DBeaverCore; import org.jkiss.dbeaver.ext.mysql.model.MySQLDataSource; import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBPDataSourceContainer; import org.jkiss.dbeaver.model.connection.DBPClientHome; import org.jkiss.dbeaver.model.connection.DBPClientManager; import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration; import org.jkiss.dbeaver.model.connection.DBPDriver; import org.jkiss.dbeaver.model.impl.jdbc.JDBCDataSourceProvider; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.OSDescriptor; import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.dbeaver.utils.WinRegistry; import org.jkiss.utils.CommonUtils; import org.jkiss.utils.StandardConstants; import java.io.File; import java.util.*; public class MySQLDataSourceProvider extends JDBCDataSourceProvider implements DBPClientManager { private static final Log log = Log.getLog(MySQLDataSourceProvider.class); private static final String REGISTRY_ROOT_MYSQL_32 = "SOFTWARE\\MySQL AB"; private static final String REGISTRY_ROOT_MYSQL_64 = "SOFTWARE\\Wow6432Node\\MYSQL AB"; private static final String REGISTRY_ROOT_MARIADB = "SOFTWARE\\Monty Program AB"; private static final String SERER_LOCATION_KEY = "Location"; private static final String INSTALLDIR_KEY = "INSTALLDIR"; //private static final String SERER_VERSION_KEY = "Version"; private static Map<String,MySQLServerHome> localServers = null; private static Map<String,String> connectionsProps; static { connectionsProps = new HashMap<>(); // Prevent stupid errors "Cannot convert value '0000-00-00 00:00:00' from column X to TIMESTAMP" // Widely appears in MyISAM tables (joomla, etc) connectionsProps.put("zeroDateTimeBehavior", "convertToNull"); // Set utf-8 as default charset connectionsProps.put("characterEncoding", GeneralUtils.UTF8_ENCODING); connectionsProps.put("tinyInt1isBit", "false"); // Auth plugins // connectionsProps.put("authenticationPlugins", // "com.mysql.jdbc.authentication.MysqlClearPasswordPlugin," + // "com.mysql.jdbc.authentication.MysqlOldPasswordPlugin," + // "org.jkiss.jdbc.mysql.auth.DialogAuthenticationPlugin"); } public static Map<String,String> getConnectionsProps() { return connectionsProps; } public MySQLDataSourceProvider() { } @Override protected String getConnectionPropertyDefaultValue(String name, String value) { String ovrValue = connectionsProps.get(name); return ovrValue != null ? ovrValue : super.getConnectionPropertyDefaultValue(name, value); } @Override public long getFeatures() { return FEATURE_CATALOGS; } @Override public String getConnectionURL(DBPDriver driver, DBPConnectionConfiguration connectionInfo) { /* String trustStorePath = System.getProperty(StandardConstants.ENV_USER_HOME) + "/.keystore"; System.setProperty("javax.net.ssl.keyStore", trustStorePath); System.setProperty("javax.net.ssl.keyStorePassword", "changeit"); System.setProperty("javax.net.ssl.trustStore", trustStorePath); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); */ StringBuilder url = new StringBuilder(); url.append("jdbc:mysql://") .append(connectionInfo.getHostName()); if (!CommonUtils.isEmpty(connectionInfo.getHostPort())) { url.append(":").append(connectionInfo.getHostPort()); } url.append("/"); if (!CommonUtils.isEmpty(connectionInfo.getDatabaseName())) { url.append(connectionInfo.getDatabaseName()); } return url.toString(); } @NotNull @Override public DBPDataSource openDataSource( @NotNull DBRProgressMonitor monitor, @NotNull DBPDataSourceContainer container) throws DBException { return new MySQLDataSource(monitor, container); } ////////////////////////////////////// // Client manager @Override public Collection<String> findClientHomeIds() { findLocalClients(); Set<String> homes = new LinkedHashSet<>(); for (MySQLServerHome home : localServers.values()) { homes.add(home.getHomeId()); } return homes; } @Override public String getDefaultClientHomeId() { findLocalClients(); return localServers.isEmpty() ? null : localServers.values().iterator().next().getHomeId(); } @Override public DBPClientHome getClientHome(String homeId) { return getServerHome(homeId); } public static MySQLServerHome getServerHome(String homeId) { findLocalClients(); MySQLServerHome home = localServers.get(homeId); return home == null ? new MySQLServerHome(homeId, homeId) : home; } public synchronized static void findLocalClients() { if (localServers != null) { return; } localServers = new LinkedHashMap<>(); // read from path String path = System.getenv("PATH"); if (path != null) { for (String token : path.split(System.getProperty(StandardConstants.ENV_PATH_SEPARATOR))) { token = CommonUtils.removeTrailingSlash(token); File mysqlFile = new File(token, MySQLUtils.getMySQLConsoleBinaryName()); if (mysqlFile.exists()) { File binFolder = mysqlFile.getAbsoluteFile().getParentFile();//.getName() if (binFolder.getName().equalsIgnoreCase("bin")) { String homeId = CommonUtils.removeTrailingSlash(binFolder.getParentFile().getAbsolutePath()); localServers.put(homeId, new MySQLServerHome(homeId, null)); } } } } // find homes in Windows registry OSDescriptor localSystem = DBeaverCore.getInstance().getLocalSystem(); if (localSystem.isWindows()) { try { // Search MySQL entries { final String registryRoot = localSystem.is64() ? REGISTRY_ROOT_MYSQL_64 : REGISTRY_ROOT_MYSQL_32; List<String> homeKeys = WinRegistry.readStringSubKeys(WinRegistry.HKEY_LOCAL_MACHINE, registryRoot); if (homeKeys != null) { for (String homeKey : homeKeys) { Map<String, String> valuesMap = WinRegistry.readStringValues(WinRegistry.HKEY_LOCAL_MACHINE, registryRoot + "\\" + homeKey); if (valuesMap != null) { for (String key : valuesMap.keySet()) { if (SERER_LOCATION_KEY.equalsIgnoreCase(key)) { String serverPath = CommonUtils.removeTrailingSlash(valuesMap.get(key)); localServers.put(serverPath, new MySQLServerHome(serverPath, homeKey)); break; } } } } } } // Search MariaDB entries { List<String> homeKeys = WinRegistry.readStringSubKeys(WinRegistry.HKEY_LOCAL_MACHINE, REGISTRY_ROOT_MARIADB); if (homeKeys != null) { for (String homeKey : homeKeys) { Map<String, String> valuesMap = WinRegistry.readStringValues(WinRegistry.HKEY_LOCAL_MACHINE, REGISTRY_ROOT_MARIADB + "\\" + homeKey); if (valuesMap != null) { for (String key : valuesMap.keySet()) { if (INSTALLDIR_KEY.equalsIgnoreCase(key)) { String serverPath = CommonUtils.removeTrailingSlash(valuesMap.get(key)); localServers.put(serverPath, new MySQLServerHome(serverPath, homeKey)); break; } } } } } } } catch (Throwable e) { log.warn("Error reading Windows registry", e); } } } }