📄 mysqlio.java
字号:
/*
* MM JDBC Drivers for MySQL
*
* $Id: MysqlIO.java,v 1.3 1998/08/25 00:53:47 mmatthew Exp $
*
* Copyright (C) 1998 Mark Matthews <mmatthew@worldserver.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* See the COPYING file located in the top-level-directory of
* the archive of this library for complete text of license.
*/
/**
* This class is used by Connection for communicating with the
* MySQL server.
*
* @see java.sql.Connection
* @author Mark Matthews <mmatthew@worldserver.com>
* @version $Id$
*/
package org.gjt.mm.mysql;
import java.io.*;
import java.net.*;
import java.util.*;
import java.sql.*;
import java.sql.SQLException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public class MysqlIO
{
private Socket _Mysql_Conn = null;
private BufferedInputStream _Mysql_Buf_Input = null;
private BufferedOutputStream _Mysql_Buf_Output = null;
private DataInputStream _Mysql_Input = null;
private DataOutputStream _Mysql_Output = null;
static int MAXBUF = 65535;
static final int HEADER_LENGTH = 4;
static final int COMP_HEADER_LENGTH = 3;
private byte _packetSequence = 0;
private byte _protocol_V = 0;
private String _Server_V = null;
private int _server_major_version = 0;
private int _server_minor_version = 0;
private int _server_sub_minor_version = 0;
private int _port = 3306;
private String _Host = null;
private Deflater _Deflater = null;
private Inflater _Inflater = null;
//
// Use this when reading in rows to avoid thousands of new()
// calls, because the byte arrays just get copied out of the
// packet anyway
//
private Buffer _ReusablePacket = new Buffer(MAXBUF);
//
// For SQL Warnings
//
java.sql.SQLWarning _Warning = null;
private static int CLIENT_LONG_PASSWORD = 1; /* new more secure passwords */
private static int CLIENT_FOUND_ROWS = 2; /* Found instead of affected rows */
private static int CLIENT_LONG_FLAG = 4; /* Get all column flags */
private static int CLIENT_CONNECT_WITH_DB = 8; /* One can specify db on connect */
private static int CLIENT_NO_SCHEMA = 16; /* Don't allow database.table.column */
private static int CLIENT_COMPRESS = 32; /* Can use compression protcol */
private static int CLIENT_ODBC = 64; /* Odbc client */
private static int CLIENT_LOCAL_FILES = 128; /* Can use LOAD DATA LOCAL */
private static int CLIENT_IGNORE_SPACE = 256; /* Ignore spaces before '(' */
private boolean use_compression = false;
/**
* Constructor: Connect to the MySQL server and setup
* a stream connection.
*
* @param host the hostname to connect to
* @param port the port number that the server is listening on
* @exception IOException if an IOException occurs during connect.
*/
MysqlIO(String Host, int port) throws IOException, java.sql.SQLException
{
_port = port;
_Host = Host;
_Mysql_Conn = new Socket(_Host, _port);
_Mysql_Buf_Input = new BufferedInputStream(_Mysql_Conn.getInputStream());
_Mysql_Buf_Output = new BufferedOutputStream(_Mysql_Conn.getOutputStream());
_Mysql_Input = new DataInputStream(_Mysql_Buf_Input);
_Mysql_Output = new DataOutputStream(_Mysql_Buf_Output);
}
/**
* Initialize communications with the MySQL server.
*
* Handles logging on, and handling initial connection errors.
*/
void init(String User, String Password) throws java.sql.SQLException
{
String Seed;
try {
// Read the first packet
Buffer Buf = readPacket();
// Get the protocol version
_protocol_V = Buf.readByte();
if (_protocol_V == -1) {
try {
_Mysql_Conn.close();
}
catch (Exception E) {}
throw new SQLException("Server configuration denies access to data source", "08001", 0);
}
_Server_V = Buf.readString();
// Parse the server version into major/minor/subminor
int point = _Server_V.indexOf(".");
if (point != -1) {
try {
int n = Integer.parseInt(_Server_V.substring(0, point));
_server_major_version = n;
}
catch (NumberFormatException NFE1) {
}
String Remaining = _Server_V.substring(point + 1, _Server_V.length());
point = Remaining.indexOf(".");
if (point != -1) {
try {
int n = Integer.parseInt(Remaining.substring(0, point));
_server_minor_version = n;
}
catch (NumberFormatException NFE2) {
}
Remaining = Remaining.substring(point + 1, Remaining.length());
int pos = 0;
while (pos < Remaining.length()) {
if (Remaining.charAt(pos) < '0' ||
Remaining.charAt(pos) > '9') {
break;
}
pos++;
}
try {
int n = Integer.parseInt(Remaining.substring(0, pos));
_server_sub_minor_version = n;
}
catch (NumberFormatException NFE3) {
}
}
}
long threadId = Buf.readLong();
Seed = Buf.readString();
if (Driver.trace) {
Debug.msg(this, "Protocol Version: " + (int)_protocol_V);
Debug.msg(this, "Server Version: " + _Server_V);
Debug.msg(this, "Thread ID: " + threadId);
Debug.msg(this, "Crypt Seed: " + Seed);
}
// Client capabilities
int clientParam = 0;
if (Buf.pos < Buf.buf_length) {
int serverCapabilities = Buf.readInt();
// Should be settable by user
if ((serverCapabilities & CLIENT_COMPRESS) != 0) {
// The following match with ZLIB's
// decompress() and compress()
//_Deflater = new Deflater();
//_Inflater = new Inflater();
//clientParam |= CLIENT_COMPRESS;
}
}
// Authenticate
if (_protocol_V > 9) {
//clientParam |= CLIENT_LONG_PASSWORD; // for long passwords
clientParam = 1;
}
else {
clientParam &= ~CLIENT_LONG_PASSWORD;
}
int password_length = 16;
int user_length = 0;
if (User != null) {
user_length = User.length();
}
int pack_length = (user_length + password_length) +
6 + HEADER_LENGTH; // Passwords can be 16 chars long
Buffer Packet = new Buffer(pack_length);
Packet.writeInt(clientParam);
Packet.writeLongInt(pack_length);
// User/Password data
Packet.writeString(User);
if (_protocol_V > 9) {
Packet.writeString(Util.newCrypt(Password, Seed));
}
else {
Packet.writeString(Util.oldCrypt(Password, Seed));
}
send(Packet);
// Check for errors
Buffer B = readPacket();
byte status = B.readByte();
if (status == (byte) 0xff) {
String Message = "";
int errno = 2000;
if (_protocol_V > 9) {
errno = B.readInt();
Message = B.readString();
clearReceive();
String XOpen = SQLError.mysqlToXOpen(errno);
if (XOpen.equals("S1000")) {
throw new java.sql.SQLException("Communication failure during handshake. Is there a server running on " + _Host + ":" + _port + "?");
}
else {
throw new java.sql.SQLException(SQLError.get(XOpen) + ": " + Message,
XOpen, errno);
}
}
else {
Message = B.readString();
clearReceive();
if (Message.indexOf("Access denied") != -1) {
throw new java.sql.SQLException(SQLError.get("28000") + ": " + Message,
"28000", errno);
}
else {
throw new java.sql.SQLException(SQLError.get("08001") + ": " + Message,
"08001", errno);
}
}
}
else if (status == 0x00) {
if (_server_major_version >= 3 &&
_server_minor_version >= 22 &&
_server_sub_minor_version >= 5) {
Packet.newReadLength();
Packet.newReadLength();
}
else {
Packet.readLength();
Packet.readLength();
}
}
else {
throw new java.sql.SQLException("Unknown Status code from server",
"08007", status);
}
//if ((clientParam & CLIENT_COMPRESS) != 0) {
//use_compression = true;
//}
}
catch (IOException E) {
E.printStackTrace();
throw new java.sql.SQLException(SQLError.get("08S01") + ": " + E.getClass().getName(), "08S01", 0);
}
}
/**
* Get the version string of the server we are talking to
*/
String getServerVersion()
{
return _Server_V;
}
/**
* Send a command to the MySQL server
*
* If data is to be sent with command, it should be put in ExtraData
*
* Raw packets can be sent by setting QueryPacket to something other
* than null.
*/
final Buffer sendCommand(int command, String ExtraData, Buffer QueryPacket) throws Exception
{
Buffer Ret = null;
byte statusCode;
try {
Buffer Packet = null;
if (QueryPacket == null) {
int pack_length = HEADER_LENGTH + COMP_HEADER_LENGTH + 1 + ExtraData.length() + 2;
Packet = new Buffer(pack_length);
_packetSequence = -1;
Packet.clear();
// Offset different for compression
if (use_compression) {
Packet.pos += COMP_HEADER_LENGTH;
}
Packet.writeByte((byte)command);
if (command == MysqlDefs.INIT_DB || command == MysqlDefs.CREATE_DB ||
command == MysqlDefs.DROP_DB || command == MysqlDefs.QUERY) {
Packet.writeStringNoNull(ExtraData);
}
else if (command == MysqlDefs.PROCESS_KILL) {
long id = new Long(ExtraData).longValue();
Packet.writeLong(id);
}
else if (command == MysqlDefs.RELOAD && _protocol_V > 9) {
Debug.msg(this, "Reload");
//Packet.writeByte(reloadParam);
}
}
else {
_packetSequence = -1;
Packet = QueryPacket;
}
send(Packet);
}
catch (Exception Ex) {
Ex.printStackTrace();
throw new java.sql.SQLException(SQLError.get("08S01") + ": "
+ Ex.getClass().getName(), "08S01", 0);
}
try {
// Check return value, if we get a java.io.EOFException,
// the server has gone away. We'll pass it on up the
// exception chain and let someone higher up decide
// what to do (barf, reconnect, etc).
Ret = readPacket();
statusCode = Ret.readByte();
}
catch (java.io.EOFException EOFE) {
throw EOFE;
}
catch (Exception FallThru) {
throw new java.sql.SQLException(SQLError.get("08S01")
+ ": " +
FallThru.getClass().getName(),
"08S01", 0);
}
try {
// Error handling
if (statusCode == (byte)0xff) {
String ErrorMessage;
int errno = 2000;
if (_protocol_V > 9) {
errno = Ret.readInt();
ErrorMessage = Ret.readString();
clearReceive();
String XOpen = SQLError.mysqlToXOpen(errno);
throw new java.sql.SQLException(SQLError.get(XOpen) +
": " + ErrorMessage,
XOpen, errno);
}
else {
ErrorMessage = Ret.readString();
clearReceive();
if (ErrorMessage.indexOf("Unknown column") != -1) {
throw new java.sql.SQLException(SQLError.get("S0022")
+ ": " + ErrorMessage,
"S0022", -1);
}
else {
throw new java.sql.SQLException(SQLError.get("S1000")
+ ": " + ErrorMessage,
"S1000", -1);
}
}
}
else if (statusCode == 0x00) {
if (command == MysqlDefs.CREATE_DB || command == MysqlDefs.DROP_DB) {
java.sql.SQLWarning NW = new java.sql.SQLWarning("Command=" + command + ": ");
if (_Warning != null)
NW.setNextException(_Warning);
_Warning = NW;
}
}
else if (Ret.isLastDataPacket()) {
java.sql.SQLWarning NW = new java.sql.SQLWarning("Command=" + command + ": ");
if (_Warning != null)
NW.setNextException(_Warning);
_Warning = NW;
}
return Ret;
}
catch (IOException E) {
throw new java.sql.SQLException(SQLError.get("08S01") + ": " + E.getClass().getName(), "08S01", 0);
}
}
/**
* Send a query stored in a packet directly to the server.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -