com.mysql.jdbc.SocketMetadata Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mysql-connector-java
Show all versions of mysql-connector-java
MySQL JDBC Type 4 driver
/*
Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
, like most MySQL Connectors.
There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
this software, see the FOSS License Exception
.
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation; version 2
of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this
program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
Floor, Boston, MA 02110-1301 USA
*/
package com.mysql.jdbc;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface SocketMetadata {
public boolean isLocallyConnected(ConnectionImpl conn) throws SQLException;
/*
* Provides a standard way of determining whether a socket connection is local.
*
* This ensures socket factories (e.g. StandardSocketFactory, StandardSSLSocketFactory) which need to implement this interface, can delegate to a generic
* implementation.
*/
static class Helper {
public static final String IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME = "com.mysql.jdbc.test.isLocalHostnameReplacement";
public static boolean isLocallyConnected(com.mysql.jdbc.ConnectionImpl conn) throws SQLException {
long threadId = conn.getId();
java.sql.Statement processListStmt = conn.getMetadataSafeStatement();
ResultSet rs = null;
String processHost = null;
// "inject" for tests
if (System.getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME) != null) {
processHost = System.getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME);
} else if (conn.getProperties().getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME) != null) {
processHost = conn.getProperties().getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME);
} else { // get it from server
try {
processHost = findProcessHost(threadId, processListStmt);
if (processHost == null) {
// http://bugs.mysql.com/bug.php?id=44167 - connection ids on the wire wrap at 4 bytes even though they're 64-bit numbers
conn.getLog()
.logWarn(String.format(
"Connection id %d not found in \"SHOW PROCESSLIST\", assuming 32-bit overflow, using SELECT CONNECTION_ID() instead",
threadId));
rs = processListStmt.executeQuery("SELECT CONNECTION_ID()");
if (rs.next()) {
threadId = rs.getLong(1);
processHost = findProcessHost(threadId, processListStmt);
} else {
conn.getLog().logError(
"No rows returned for statement \"SELECT CONNECTION_ID()\", local connection check will most likely be incorrect");
}
}
} finally {
processListStmt.close();
}
}
if (processHost != null) {
conn.getLog().logDebug(String.format("Using 'host' value of '%s' to determine locality of connection", processHost));
int endIndex = processHost.lastIndexOf(":");
if (endIndex != -1) {
processHost = processHost.substring(0, endIndex);
try {
boolean isLocal = false;
InetAddress[] allHostAddr = InetAddress.getAllByName(processHost);
// mysqlConnection should be the raw socket
SocketAddress remoteSocketAddr = conn.getIO().mysqlConnection.getRemoteSocketAddress();
if (remoteSocketAddr instanceof InetSocketAddress) {
InetAddress whereIConnectedTo = ((InetSocketAddress) remoteSocketAddr).getAddress();
for (InetAddress hostAddr : allHostAddr) {
if (hostAddr.equals(whereIConnectedTo)) {
conn.getLog().logDebug(
String.format("Locally connected - HostAddress(%s).equals(whereIconnectedTo({%s})", hostAddr, whereIConnectedTo));
isLocal = true;
break;
}
conn.getLog()
.logDebug(String.format("Attempted locally connected check failed - ! HostAddress(%s).equals(whereIconnectedTo(%s)",
hostAddr, whereIConnectedTo));
}
} else {
String msg = String.format("Remote socket address %s is not an inet socket address", remoteSocketAddr);
conn.getLog().logDebug(msg);
}
return isLocal;
} catch (UnknownHostException e) {
conn.getLog().logWarn(Messages.getString("Connection.CantDetectLocalConnect", new Object[] { processHost }), e);
return false;
}
}
conn.getLog().logWarn(String
.format("No port number present in 'host' from SHOW PROCESSLIST '%s', unable to determine whether locally connected", processHost));
return false;
}
conn.getLog().logWarn(String
.format("Cannot find process listing for connection %d in SHOW PROCESSLIST output, unable to determine if locally connected", threadId));
return false;
}
private static String findProcessHost(long threadId, java.sql.Statement processListStmt) throws SQLException {
String processHost = null;
ResultSet rs = processListStmt.executeQuery("SHOW PROCESSLIST");
while (rs.next()) {
long id = rs.getLong(1);
if (threadId == id) {
processHost = rs.getString(3);
break;
}
}
return processHost;
}
}
}